Created
June 18, 2015 03:54
-
-
Save Logan676/bb2c7f5a5b85f83b5271 to your computer and use it in GitHub Desktop.
implement multi-selection and Contextual ActionMode in ActionBarSherlock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.os.Bundle; | |
import android.support.v4.app.DialogFragment; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.AbsListView; | |
import android.widget.ListView; | |
import com.actionbarsherlock.app.SherlockListFragment; | |
import com.actionbarsherlock.view.ActionMode; | |
import com.actionbarsherlock.view.Menu; | |
public final class LibraryFragment extends SherlockListFragment { | |
private MyListAdapter adapter; | |
private ListView list; | |
// if ActoinMode is null - assume we are in normal mode | |
private ActionMode actionMode; | |
@Override | |
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { | |
View v = inflater.inflate(R.layout.fragment_library, null); | |
this.list = (ListView) v.findViewById(android.R.id.list); | |
this.initListView(); | |
return v; | |
} | |
@Override | |
public void onPause() { | |
super.onPause(); | |
if (this.actionMode != null) { | |
this.actionMode.finish(); | |
} | |
} | |
@Override | |
public void onResume() { | |
super.onResume(); | |
updateData(); | |
} | |
// update ListView | |
protected void updateData() { | |
if (adapter == null) { | |
return; | |
} | |
adapter.clear(); | |
// my kinda stuff :) | |
File[] items = scan(); | |
if (items != null) { | |
adapter.updateData(items); | |
if (actionMode != null) { | |
actionMode.invalidate(); | |
} | |
} | |
// if empty - finish action mode. | |
if (actionMode != null && (files == null || files.length == 0)) { | |
actionMode.finish(); | |
} | |
} | |
private void initListView() { | |
this.adapter = new MyAdapter(getActivity()); | |
this.list.setAdapter(adapter); | |
this.list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { | |
@Override | |
public boolean onItemLongClick(AdapterView<?> arg0, | |
View arg1, int arg2, long arg3) { | |
if (actionMode != null) { | |
// if already in action mode - do nothing | |
return false; | |
} | |
// set checked selected item and enter multi selection mode | |
list.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); | |
list.setItemChecked(arg2, true); | |
getSherlockActivity().startActionMode( | |
new ActionModeCallback()); | |
return true; | |
} | |
}); | |
this.list.setOnItemClickListener(new AdapterView.OnItemClickListener() { | |
@Override | |
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, | |
long arg3) { | |
if (actionMode != null) { | |
// the items are auomatically "checked" becaise we've set AbsListView.CHOICE_MODE_MULTIPLE before | |
// starting action mode, so the only thing we have to care about is invalidating the actionmode | |
actionMode.invalidate(); //invalidate title and menus. | |
} else { | |
// do whatever you should on item click | |
} | |
} | |
}); | |
} | |
// all our ActionMode stuff here :) | |
private final class ActionModeCallback implements ActionMode.Callback { | |
// " selected" string resource to update ActionBar text | |
private String selected = getActivity().getString( | |
R.string.library_selected); | |
@Override | |
public boolean onCreateActionMode(ActionMode mode, Menu menu) { | |
actionMode = mode; | |
return true; | |
} | |
@Override | |
public boolean onPrepareActionMode(ActionMode mode, Menu menu) { | |
// remove previous items | |
menu.clear(); | |
final int checked = list.getCheckedItemCount(); | |
// update title with number of checked items | |
mode.setTitle(checked + this.selected); | |
switch (checked) { | |
case 0: | |
// if nothing checked - exit action mode | |
mode.finish(); | |
return true; | |
case 1: | |
// all items - rename + delete | |
getSherlockActivity().getSupportMenuInflater().inflate( | |
R.menu.library_context, menu); | |
return true; | |
default: | |
getSherlockActivity().getSupportMenuInflater().inflate( | |
R.menu.library_context, menu); | |
// remove rename option - because we have more than one selected | |
menu.removeItem(R.id.library_context_rename); | |
return true; | |
} | |
} | |
@Override | |
public boolean onActionItemClicked(ActionMode mode, | |
com.actionbarsherlock.view.MenuItem item) { | |
SparseBooleanArray checked; | |
switch (item.getItemId()) { | |
case R.id.library_context_rename: | |
// the rename action is present only when only one item is selected. | |
// so when the first checked item found, show the dialog and break | |
checked = list.getCheckedItemPositions(); | |
for (int i = 0; i < checked.size(); i++) { | |
final int index = checked.keyAt(i); | |
if (checked.get(index)) { | |
final DialogFragment d = RenameDialog.instantiate(adapter.getItem(index).getFile(), LibraryFragment.this); | |
d.show(getActivity().getSupportFragmentManager(), "dialog"); | |
break; | |
} | |
} | |
return true; | |
case R.id.library_context_delete: | |
// delete every checked item | |
checked = list.getCheckedItemPositions(); | |
for (int i = 0; i < checked.size(); i++) { | |
final int index = checked.keyAt(i); | |
if (checked.get(index)) { | |
adapter.getItem(index).getFile().delete(); | |
} | |
} | |
updateData(); | |
return true; | |
default: | |
return false; | |
} | |
} | |
@Override | |
public void onDestroyActionMode(ActionMode mode) { | |
list.clearChoices(); | |
//workaround for some items not being unchecked. | |
//see http://stackoverflow.com/a/10542628/1366471 | |
for (int i = 0; i < list.getChildCount(); i++) { | |
(list.getChildAt(i).getBackground()).setState(new int[]{0}); | |
} | |
list.setChoiceMode(AbsListView.CHOICE_MODE_NONE); | |
actionMode = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment