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:
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).