Batch contextual action mode - android

I want to enable multiple view selection on longClick(). Should I declare an action mode object and call startActionMode()? Also, how would I change menu list for single item click? I used the documentation as reference, as shown.
ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
// Here you can do something when items are selected/de-selected,
// such as update the title in the CAB
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// Respond to clicks on the actions in the CAB
switch (item.getItemId()) {
case R.id.menu_delete:
deleteSelectedItems();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate the menu for the CAB
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context, menu);
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
// Here you can make any necessary updates to the activity when
// the CAB is removed. By default, selected items are deselected/unchecked.
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// Here you can perform updates to the CAB due to
// an invalidate() request
return false;
}
});

To change menu list for single item click following is the code.
int count=0;
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
if (checked) {
count++;
} else {
count--;
}
mode.invalidate(); // Add this to Invalidate CAB so that it calls onPrepareActionMode
}
Now modify the onPrepareActionMode as follows
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
if (selCount == 1){
//show the menu here that you want if only 1 item is selected
} else {
//show the menu here that you want if more than 1 item is selected
}
}

Related

Focus ListView Items on Button Click

Is it possible to focus the List View Items through any button click?
Like i want that when user click on Floating Action Button then the listview gets focused. I dont want to show checkbox type layout on button clicked. I just want to show the same like in the screenshot on Button click.
What i did is I put the listview onItemLongClick code in the button click blocks but it doesnot work.
fabButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
listViewMessages.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listViewMessages.setMultiChoiceModeListener(new MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
tv.setText(listViewMessages.getCheckedItemCount()+ " Selected");
}
#Override
public boolean onActionItemClicked(final ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu:
}
});
mode.finish();
return true;
default:
return false;
}
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate the menu for the CAB
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.contextual, menu);
fabButton.setVisibility(View.INVISIBLE);
fabButtonn.setVisibility(View.VISIBLE);
fabButtonn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
for ( int i=0; i< messageListAdapter.getCount(); i++ ) {
listViewMessages.setItemChecked(i, true);
}
}
});
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
fabButton.setVisibility(View.VISIBLE);
fabButtonn.setVisibility(View.GONE);
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// Here you can perform updates to the CAB due to
// an invalidate() request
return false;
}
});
With this code if user clcik on button then he/she has too long press items again to focus the list items which is not what i want. I want to focus items right when button click. Any explanation or link provided will be helpful

CAB menu not working

I Have a tablayout, within which in each tab, i have listviews that use custom adapters. I have setup the listview to Multi MODAL and defined a cabmenu. I have used the same cabmenu in another activity having similar tabs and listviews. I dont understand what i am missing , the cab menu is not appearing on long press on the listview items. The only difference between the other activity and this one is, the other has an action bar. Below is the code where the cab menu isnt working.
public void showLists(){
adapter=new CustomItemAdapter(getActivity(),listtype,fruititem,listid);
lv=(ListView) getView().findViewById(R.id.fruits);
lv.setAdapter(adapter);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
lv.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
if (checked) {
selection.add(fruititem.get(position));
count++;
} else {
selection.remove(fruititem.get(position));
count--;
}
TextView tv = (TextView) getActivity().getLayoutInflater().inflate(R.layout.contextual_title, null);
tv.setText(count + " selected");
mode.setCustomView(tv);
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater menuinflater = new MenuInflater(getContext());
menuinflater.inflate(R.menu.cabmenu, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (item.getItemId() == R.id.deleteic) {
for (ItemLists s : selection) {
dbHandler.deleteItem(s);
}
adapter.notifyDataSetChanged();
mode.finish();
showLists();
}
mode.finish();
return true;
}#Override
public void onDestroyActionMode(ActionMode mode) {
count = 0;
selection.clear();
}
});
}

Android ListView Single Choice Mode with Action Mode

I would like to create an app screen that include one ListView.
When the user performs long press on ListView item, I would like to show action mode. I implemented it with the following code and I got the result which I want.
One problem is that I would like to allow the user to select only one list item and select the context menu item in action mode to do the operation. The following code is allowed the user to select multiple list items.
Is android not support ListView.CHOICE_MODE_SINGLE_MODAL choice mode? I had spend a lot of time in Googling but can't find any reference to implement which allows a single choice mode with context action mode. Please help.
mTestListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mTestListView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode actionMode, int position, long l, boolean value) {
}
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = actionMode.getMenuInflater();
inflater.inflate(R.menu.context_menu_test_single_choice_mode, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_done:
Toast.makeText(getActivity(), "Done", Toast.LENGTH_SHORT).show();
actionMode.finish();
adapter.notifyDataSetChanged();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
}
});
}
Add this code in your method. This code will check item count. If count exceed more than one, it will remove other item except the last one.
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
int selectCount = mList.getCheckedItemCount();
if(selectCount > 1){
SparseBooleanArray checkarr = mList.getCheckedItemPositions();
for(int i=0;i<dataList.size();i++){
/*
check item is checked
and not the last item
* */
if(checkarr.get(i) && position != i){
mList.setItemChecked(i, false);
break;
}
}
}
}
I tried in my app. It works. :). Hope this will help you.

Hide Items in Context Action Bar (CAB) dynamically when multiple items are selected

I have a listActivity that shows CAB on long click. If more than 1 item is selected I would like to hide one of my menu items.
I keep track of the # of items selected in onItemCheckedStateChanged(). However I don't have access to the menu to remove the item from this function. See comments in code below to get an idea of what I was trying. I feel like I am missing some simple core understanding... code below is called from my onCreate() function.
private void setupActionBarContext() {
ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
private int selCount = 0;
ArrayList<Long> idList = new ArrayList<Long>();
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
if (checked) {
selCount++;
idList.add(id);
} else {
selCount--;
idList.remove(id);
}
mode.setTitle(selCount + " selected");
// I WOULD LIKE TO HIDE ITEM ON MENU IF 'selCount' IS > 1
// For example something like this...
// if (selCount > 1) {
// MenuItem item = menu.findItem(R.id.edit_item);
// item.setVisible(false);
// } else {
// MenuItem item = menu.findItem(R.id.edit_item);
// item.setVisible(false);
// }
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.delete_item:
for(Long i: idList){
mDbHelper.deleteItem(i);
}
mode.finish();
return true;
case R.id.edit_item:
Toast.makeText(getBaseContext(), "Edit Item", Toast.LENGTH_SHORT).show();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate the menu for the CAB
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
selCount = 0;
idList.clear();
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
});
And my menu item...
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/edit_item"
android:title="#string/edit_item"
android:showAsAction="ifRoom"
android:orderInCategory="1"/>
<item android:id="#+id/delete_item"
android:title="#string/delete_item"
android:icon="#drawable/ic_action_delete"
android:showAsAction="ifRoom"
android:orderInCategory="2"/>
</menu>
As suggested in adneal's comment.
Add invalidate() to onItemCheckedStateChanged()
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
if (checked) {
selCount++;
idList.add(id);
} else {
selCount--;
idList.remove(id);
}
mode.setTitle(selCount + " selected");
mode.invalidate(); // Add this to Invalidate CAB
}
This invalidates the CAB and causes the onPrepareActionMode() function to be called.
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
if (selCount == 1){
MenuItem item = menu.findItem(R.id.edit_item);
item.setVisible(true);
return true;
} else {
MenuItem item = menu.findItem(R.id.edit_item);
item.setVisible(false);
return true;
}
}

Passing id of ListView item to ActionMode.Callback object

So my problem right now is that right now I am long clicking an item in a ListView which brings up a contextual action bar. The id passed into onItemLongClick is the variable that I would like to use in the mActionModeCallback's on ActionItemClicked() method. This seems like it would be a fairly common procedure since if a user is editing a list of items, you would want to access the id of that row in the database somehow when the user clicked an "edit" or a "delete" action.
listView.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> p, View view, int pos, long id) {
//The id of the row in the database
long variableThatIWantToPassToCallback = id;
mActionMode = getActivity().startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
public boolean onCreateActionMode(ActionMode mode, Menu menu) {}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
//I would like access to the id of the clicked item here, NOT item.getItemId()
}
public void onDestroyActionMode(ActionMode mode) {}
};
The proper way to do this is to call mActionMode.setTag("1") in onItemCheckedStateChanged and then from the onActionItemClicked function call mode.getTag();
Create your own callback by extending the interface ActionMode.Callback
private interface ActionCallback extends ActionMode.Callback {
public void setClickedView(View view);
}
private ActionCallback mActionModeCallback = new ActionCallback() {
public View mClickedView;
public void setClickedView(View view) {
mClickedView = view;
}
// Called when the action mode is created; startActionMode() was called
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
return true;
}
// Called each time the action mode is shown. Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item ) {
switch ( item.getItemId() ) {
case R.id.menu_delete:
Log.v( TAG, "#onActionItemClicked ready to delete the item with id: " + mClickedView.getTag() );
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
} // end switch
}
// Called when the user exits the action mode
#Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
For a view which has OnLongClickListener attached, override the onLongClick callback this way.
#Override
// Called when the user long-clicks on someView
public boolean onLongClick( View view ) {
// proceed only when actionmode is not null
// otherwise overlapping action modes will be
// displayed
if( mActionMode != null ) {
return false;
}
mActionModeCallback.setClickedView(view);
// Start the CAB using the ActionMode.Callback defined above
mActionMode = startActionMode( mActionModeCallback );
view.setSelected(true);
return true;
}

Categories

Resources