I've got a silly little problem. I've registered a ListFragment
both as OnItemClickListener
and OnItemLongClickListener
of its own ListView
.
When the onItemClick
event is called, an intent for the detail view activity of that item is started, no problems there.
When the onItemLongClick
event happens, I want to accomplish the following things:
- Create a CAB
- Keep the long-pressed item selected
Code:
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if(this.cabMode != null)
return false;
this.cabMode = getActivity().startActionMode(editModeCallback);
view.setSelected(true);
return true;
}
The CAB will show, however, the selection won't stay with the item.
Some bits and pieces, in case they are relevant: I've read about fixing this issue with calls to view.requestFocusFromTouch()
or using listView.setItemChecked()
, but that didn't work for me. Also, the views for the list items are instanced from a custom layout, but don't have any custom event listeners attached.
Any help is appreciated. Thx!
It's possible, but just barely... I actually don't know how such a simple thing can wind up so ridiculously complicated.
The key to the answer can be found here: Android: keep blue background after ListView selection
What this boils down to is to define an additional style that is used by the ListView
and setting the choice mode to AbsListView.CHOICE_MODE_SINGLE
(as explained in the linked answer).
This allows you programmatically toggle the selection using Listview.setItemChecked()
. However, you need to keep track of the index of the touched item in the onItemLongClick
callback yourself, because ListView.setSelection()
won't do that (at least ListView.getSelectedItem()
will always return -1 as far as I can see).
Code (for simplicity, my fragment implements all three OnItemClickListener
, OnItemLongClickListener
, and
ActionMode.Callback
):
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
this.listViewAdapter = new ListViewAdapter();
this.root = (ListView)inflater.inflate(R.layout.fragment_bookmarks, container, false);
this.root.setAdapter(this.listViewAdapter);
this.root.setOnItemClickListener(this);
this.root.setOnItemLongClickListener(this);
this.root.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
return this.root;
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if(this.cabMode != null)
return false;
this.selectedPosition = position;
this.root.setItemChecked(position, true);
this.root.setOnItemClickListener(null);
this.cabMode = getActivity().startActionMode(this);
return true;
}
And finally, if you want to get rid of the selection when the CAB is closed:
@Override
public void onDestroyActionMode(ActionMode mode) {
cabMode = null;
this.root.setItemChecked(this.selectedPosition, false);
this.selectedPosition = -1;
this.root.setOnItemClickListener(this);
}
Registering and unregistering the OnItemClickListener
makes sure that while the CAB is active you won't accidentally trigger the action usually associated with the item (like opening a detail view).
My solution:(trick)
final ListView lvMain = (ListView) activity.findViewById(R.id.listTHEMES);
lvMain.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
lvMain.setItemsCanFocus(false);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity,
android.R.layout.simple_list_item_multiple_choice, ArrayTheme);
lvMain.setAdapter(adapter);
lvMain.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int pos, long id) {
// TODO Auto-generated method stub
if (lvMain.isItemChecked(pos)){lvMain.setItemChecked(pos,false);}else{lvMain.setItemChecked(pos,true);}
Log.v(LOG_TAG,"long clicked pos: " + pos);
//lvMain.setSelection();
return true;
}
});
lvMain.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//Log.d(LOG_TAG, "itemClick: position = " + position + ", id = " + id);
if (lvMain.isItemChecked(position)){lvMain.setItemChecked(position,false);}else{lvMain.setItemChecked(position,true);}
}
});