I have a fragment which contains an ExpandableListView
. I would like to be able to select and delete items by group. I would also like to be able to select multiple group items for deletion, via a contextual action bar.
So far, I can click on groups to view children, and I can click on children to go to another Activity. I set the choice mode of the ExpandableListView
to be CHOICE_MODE_MULTIPLE_MODAL
, and it If I long click on a group, it is selected, a contextual action bar appears. If I select my delete button, the item is deleted. All good.
However, the problem arises when I attempt to select multiple groups in the CAB mode. It just doesn't work. If I click a second group, that group is expanded (not selected). I want to be able to just highlight multiple group items without any expansion occurring.
There's quite a lot of code to get this working, but I'll try to show some pertinent bits. The main issue is getting a list of selected group items. Secondarily, I don't want the groups to be expanded as they're selected (whilst the CAB is visible - this is what I am attempting by holding onto the ActionMode in mActionMode
).
Any help is greatly appreciated.
ex.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
@Override
public void onItemCheckedStateChanged(ActionMode actionMode, int position, long id, boolean checked) {
// Ignore long clicks on children
long pos = ex.getExpandableListPosition(position);
if (checked && (ExpandableListView.getPackedPositionType(pos) == ExpandableListView.PACKED_POSITION_TYPE_CHILD)) {
ex.setItemChecked(position, false);
return;
}
}
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = actionMode.getMenuInflater();
inflater.inflate(R.menu.context_delete_items, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
mActionMode = actionMode;
return false;
}
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem item) {
// If delete is clicked, delete the measurement set
switch(item.getItemId()) {
case(R.id.context_menu_delete_item):
Set<mySet> setsToDelete = new HashSet<mySet>();
if (ex != null) {
if (ex.getCheckedItemCount() > 0) {
SparseBooleanArray checkedPositions = ex.getCheckedItemPositions();
for (int i = 0; i < checkedPositions.size(); i++) {
int position = checkedPositions.keyAt(i);
/* Ignore selected children */
long pos = ex.getExpandableListPosition(position);
int groupPosition = ExpandableListView.getPackedPositionGroup(pos);
if (checkedPositions.valueAt(i)) {
Log.d(TAG, "Adding MeasurementSet at position Key = " + position + " to deletion list");
setsToDelete.add(mSets.get(groupPosition));
}
}
}
}
try {
if (ex != null && setsToDelete.size() > 0) {
ArrayList setsToDeleteList = new ArrayList(setsToDelete);
deleteSets(setsToDeleteList);
for (mySet s : setsToDelete) {
mSets.remove(s);
}
Toast.makeText(getActivity(), "Set deleted successfully", Toast.LENGTH_LONG).show();
}
} catch (SQLiteException sqlex) {
Log.e(TAG, "Delete operation failed");
Log.e(TAG, "Error was: " + sqlex.getMessage());
Log.e(TAG, "Stack trace: " + sqlex.getStackTrace());
Toast.makeText(getActivity(), "There was an error whilst deleting Set(s): " + sqlex.getMessage(), Toast.LENGTH_LONG).show();
}
actionMode.finish();
return true;
default:
return false;
}
}
@Override
public void onDestroyActionMode(ActionMode actionMode) {
mActionMode = null;
}
});
ex.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Long mId = mSets.get(groupPosition).getMyList().get(childPosition).getId();
Intent intent = new Intent(getActivity(), ViewSingleActivity.class);
intent.putExtra(getResources().getString(R.string.EXTRA_MID_KEY), measurementId);
startActivityForResult(intent, Constants.REQ_VIEW_M);
return true;
}
});
// Here I was trying to intercept group clicks and force the clicked group to collapse. Although this doesn't seem to solve the issue of having the group "selected"
ex.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
if (mActionMode != null) {
Log.d(TAG, "mActionMode is not null. Setting View: " + parent.toString() + " to be selected");
v.setSelected(true);
Log.d(TAG, "Collapsing group " + groupPosition);
parent.collapseGroup(groupPosition);
}
return false;
}
});
}
parent.setItemChecked(groupPosition, true)
insideonGroupClick()
causes my group items to be selected, and allows me to delete multiple groups. Sadly, I still cannot 1) style the group to show it as selected (change background colour, etc.) 2) stop the group from expanding when it is clicked (only when the CAB is visible). – Ribbonandroid:background="?android:attr/activatedBackgroundIndicator"
– Purchasable<CheckedTextView>
and this approach did not work. I changed it to be a<LinearLayout>
containing a<TextView>
, and now my group items show as selected! Thanks! But, is there some way to change the highlight colour? Thanks again. – Ribbonelv.getExpandableListPosition(flatPosition)
gives you the packed position.ExpandableListView.getPackedPositionGroup(packedPosition)
gives you the group position regardless of expanded or not. – Purchasable