Friends,
I am trying to write a application which use checkbox in ExpandableListView, I got a problem here which is maintaining checkbox state of the application, I
ExpandableListView with multiselect. Tested on API 4.3 and 4.0.3 This code also correctly handles changing screen orientation. Blocking groups made to work properly with the selected elements through SparseBooleanArray.
I hope this sample code will help :)
Activity
ExpandableListView list;
ArrayList cat = new ArrayList();
private YourAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
list = (ExpandableListView)findViewById(R.id.list);
mAdapter = new YourAdapter(this, list, cat);
if(savedInstanceState == null)
//collect your data
list.setAdapter(mAdapter);
list.setItemsCanFocus(false);
list.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
list.setOnChildClickListener(this);
list.setOnGroupClickListener(this);
}
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
return cat.get(groupPosition).selected;
}
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
YouCat cat = new YouCat();
YouSubCat subcat = new YouSubCat();
subcat = cat.get(groupPosition).sub.get(childPosition);
subcat.selected = !cat.get(groupPosition).sub.get(childPosition).selected;
cat.get(groupPosition).sub.set(childPosition, subcat);
boolean isGroupHasSelected = false;
for(int i = 0; i < cat.get(groupPosition).sub.size() && !isGroupHasSelected; i ++){
isGroupHasSelected = cat.get(groupPosition).sub.get(i).selected;
}
cat = cat.get(groupPosition);
cat.selected = isGroupHasSelected;
cat.set(groupPosition, cat);
//mAdapter.notifyDataSetChanged();
int position = parent.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition));
parent.setItemChecked(position, subcat.selected);
return true;
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//restore data
cat = (ArrayList) savedInstanceState.getSerializable("cat");
Type selType = new TypeToken() {}.getType();
SparseBooleanArray checked = new Gson().fromJson(savedInstanceState.getString("sel"), selType);
//set new data to adapter and refresh
mAdapter.refreshList(cat);
}
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
//save data and selection from list to bundle
savedInstanceState.putSerializable("cat", cat);
savedInstanceState.putString("sel", new Gson().toJson(list.getCheckedItemPositions()).toString());
}
Adapter
public class YouAdapter extends BaseExpandableListAdapter{
private Context context;
private List mGroupCollection;
private ExpandableListView mExpandableListView;
public YouAdapter(Context context, ExpandableListView pExpandableListView,
List pGroupCollection) {
this.context = context;
this.mGroupCollection = pGroupCollection;
this.mExpandableListView = pExpandableListView;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return mGroupCollection.get(groupPosition).sub.get(childPosition).name;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
class ChildHolder {
CheckBox checkBox;
TextView name, desc;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
ChildHolder childHolder;
if( convertView == null ){
convertView = LayoutInflater.from(context).inflate(R.layout.childrow, null);
childHolder = new ChildHolder();
childHolder.checkBox = (CheckBox) convertView.findViewById(R.id.myCheckBox);
childHolder.name=(TextView)convertView.findViewById(R.id.textView1);
childHolder.desc=(TextView)convertView.findViewById(R.id.textView2);
convertView.setTag(childHolder);
}else{
childHolder = (ChildHolder) convertView.getTag();
}
childHolder.name.setText(mGroupCollection.get(groupPosition).sub.get(childPosition).name);
childHolder.desc.setText(mGroupCollection.get(groupPosition).sub.get(childPosition).desc);
childHolder.checkBox.setChecked(mGroupCollection.get(groupPosition).sub.get(childPosition).selected);
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return mGroupCollection.get(groupPosition).sub.size();
}
@Override
public Object getGroup(int groupPosition) {
return mGroupCollection.get(groupPosition);
}
@Override
public int getGroupCount() {
return mGroupCollection.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
class GroupHolder {
TextView title;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
GroupHolder groupHolder;
if( convertView == null ){
convertView = LayoutInflater.from(context).inflate(R.layout.grouplayout,null);
groupHolder = new GroupHolder();
groupHolder.title = (TextView)convertView.findViewById( R.id.text1 );
convertView.setTag(groupHolder);
}else{
groupHolder = (GroupHolder) convertView.getTag();
}
groupHolder.title.setText(mGroupCollection.get(groupPosition).name);
return convertView;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
public void refreshList(List collection){
mGroupCollection = collection;
notifyDataSetChanged();
for(int g = 0; g < mGroupCollection.size(); g ++){
if(mGroupCollection.get(g).selected)
mExpandableListView.expandGroup(g);
else
mExpandableListView.collapseGroup(g);
}
}
}
YouCat class
public class YouCat implements Serializable {
private static final long serialVersionUID = 2070450081971040619L;
public String name = null;
public boolean selected = false;
public ArrayList sub = new ArrayList();
}
YouSubCat class
public class YouSubCat implements Serializable {
private static final long serialVersionUID = -1487507723105914936L;
public String name = null, desc = null;
public boolean selected = false;
}
Child row layout
Group layout
Get selected child items
final SparseBooleanArray checkedItems = list.getCheckedItemPositions();
for (int i = 0; i < checkedItems.size(); i++) {
if(checkedItems.valueAt(i))
data = ((String)list.getItemAtPosition(checkedItems.keyAt(i)));
}