带有checkbox的Android ExpandableListView,控制选中状态

朋友们,

我试图编写一个应用程序使用checkboxExpandableListView,我在这里有一个问题,这是维持应用程序的checkbox状态,我从这里得到的例子,我的问题是保持checkbox的状态,每当我检查其中一个checkbox和展开列表,checkbox没有他们应该有的检查状态。 我试图维护通过添加ArrayList来存储商店的位置和重新加载getChildView()中的位置,但仍然没有达到我想要做的。 这是我的代码

public class ElistCBox extends ExpandableListActivity { private static final String LOG_TAG = "ElistCBox"; ArrayList<String > chkState = new ArrayList<String>(); static final String colors[] = {"grey","blue","yellow","red"}; static final String shades[][] ={ { "lightgrey","#D3D3D3","dimgray","#696969", "sgi >gray 92","#EAEAEA"}, { "dodgerblue 2","#1C86EE","steelblue >2","#5CACEE","powderblue","#B0E0E6"}, { "yellow 1","#FFFF00", "gold 1","#FFD700","darkgoldenrod 1"," #FFB90F" }, {"indianred 1","#FF6A6A", "firebrick 1","#FF3030", "maroon","#800000" } }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); SimpleExpandableListAdapter expListAdapter = new SimpleExpandableListAdapter( this, createGroupList(), R.layout.group_row, new String[] { "colorName" }, new int[] { R.id.childname }, createChildList(), R.layout.child_row, new String[] { "shadeName", "rgb" }, new int[] { R.id.childname, R.id.rgb } ) { @Override public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { final View v = super.getChildView(groupPosition, childPosition, isLastChild, convertView, parent); final CheckBox chkColor = (CheckBox)v.findViewById(R.id.check1); if(chkState.contains(groupPosition+","+childPosition)){ chkColor.setChecked(true); }else{ chkColor.setChecked(false); } chkColor.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.e("Checkbox Onclick Listener", Integer.toString(groupPosition) + " - " + Integer.toString(childPosition)); } }); chkColor.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { Log.e("Checkbox check change Listener", Integer.toString(groupPosition) + " - " + Integer.toString(childPosition)); if(chkColor.isChecked()){ chkState.add(groupPosition+","+childPosition); } else { chkState.remove(groupPosition+","+childPosition); } } }); return super.getChildView(groupPosition, childPosition, isLastChild, convertView, parent); } }; setListAdapter( expListAdapter ); } public void onContentChanged () { super.onContentChanged(); Log.e( LOG_TAG, "onContentChanged" ); } public boolean onChildClick( ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { Log.e( LOG_TAG, "onChildClick: "+childPosition ); CheckBox cb = (CheckBox)v.findViewById( R.id.check1 ); if( cb != null ) cb.toggle(); return false; } public void onGroupExpand (int groupPosition) { Log.e( LOG_TAG,"onGroupExpand: "+groupPosition ); } private List createGroupList() { ArrayList result = new ArrayList(); for( int i = 0 ; i < colors.length ; ++i ) { HashMap m = new HashMap(); m.put( "colorName",colors[i] ); result.add( m ); } return (List)result; } private List createChildList() { ArrayList result = new ArrayList(); for( int i = 0 ; i < shades.length ; ++i ) { ArrayList secList = new ArrayList(); for( int n = 0 ; n < shades[i].length; n += 2 ) { HashMap child = new HashMap(); child.put( "shadeName", shades[i][n] ); child.put( "rgb", shades[i][n+1] ); secList.add( child ); } result.add( secList ); } return result; } } 

Solutions Collecting From Web of "带有checkbox的Android ExpandableListView,控制选中状态"

这是我对这个问题的回答,你需要保持一个单独的孩子的检查状态,并点击孩子时检查它。 经过一番研究,这是由于Android的视图生命周期导致视图刷新,从而不保持状态。

 public class MyExpandableListAdapter extends BaseExpandableListAdapter { //Variables // Sample data set. children[i] contains the children (String[]) for groups[i]. private String[] groups = { "People Names", "Dog Names", "Cat Names", "Fish Names" }; //headers private String[][] children = { { "Arnold", "Barry", "Chuck", "David" }, { "Ace", "Bandit", "Cha-Cha", "Deuce" }, { "Fluffy", "Snuggles" }, { "Goldy", "Bubbles" } }; private String[] group_vaues = {"PN", "DN", "CN", "FN"}; private String[][] children_values = { { "Ar", "Ba", "Ch", "Da" }, { "Ace", "Ban", "Cha", "Deu" }, { "Flu", "Snu" }, { "Gol", "Bub" } }; ArrayList<ArrayList<Integer>> check_states = new ArrayList<ArrayList<Integer>>(); private Context context; //Constructors public MyExpandableListAdapter() { } public MyExpandableListAdapter(Context c) { this.context = c; } //Set Methods public void setGroupsAndValues(String[] g, String[] v) { this.groups = g; this.group_vaues = v; } public void setChildrenAndValues(String[][] c, String[][] v) { this.children = c; this.children_values = v; //initialize the states to all 0; for(int i = 0; i < c.length; i++) { ArrayList<Integer> tmp = new ArrayList<Integer>(); for(int j = 0; j < c[i].length; j++) { tmp.add(0); } check_states.add(tmp); } } //Get Methods public Object getChild(int groupPosition, int childPosition) { return children[groupPosition][childPosition]; } public long getChildId(int groupPosition, int childPosition) { return childPosition; } public int getChildrenCount(int groupPosition) { return children[groupPosition].length; } public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { View grid; LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); grid = inflater.inflate(R.layout.specialty_list_item, parent, false); final int grpPos = groupPosition; final int childPos = childPosition; TextView header = (TextView)grid.findViewById(R.id.title); header.setText(getChild(groupPosition, childPosition).toString()); final View tick = grid.findViewById(R.id.image); if(check_states.get(grpPos).get(childPos) == 1) tick.setVisibility(View.VISIBLE); else tick.setVisibility(View.GONE); grid.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { check_states.get(grpPos).set(childPos, 1); tick.setVisibility(View.VISIBLE); } }); return grid; } public Object getGroup(int groupPosition) { return groups[groupPosition]; } public int getGroupCount() { return groups.length; } public long getGroupId(int groupPosition) { return groupPosition; } public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { View grid; if(convertView==null){ grid = new View(context); LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); grid = inflater.inflate(R.layout.specialty_header, parent, false); }else{ grid = (View)convertView; } TextView header = (TextView)grid.findViewById(R.id.specialty_header); header.setText(getGroup(groupPosition).toString()); return grid; } public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } public boolean hasStableIds() { return true; } 

}

我也有这个问题。 最后我find了根本原因和解决办法。 为了解决这个问题,而不是设置CheckBox的checkState,你应该设置其包含listView的checkState。

  public class MyExpandableListViewAdapter extends BaseExpandableListAdapter { .... private boolean[][] checkedState; private void prepareData() { checkedState =new boolean[itemData.length][]; for (int i=0; i<itemData.length; i++) { groupData.append(i, String.format("Group %d", i)); checkedState[i] = new boolean[itemData[i].length]; Arrays.fill(checkedState[i],false); } } @Override public View getChildView(final int groupPosition, final int childPosition,boolean isLastChild, View convertView, ViewGroup parent) { View itemView = convertView; final ViewHolder vh; if (itemView == null) { LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); itemView = inflater.inflate(R.layout.item_view, null); vh = new ViewHolder(); vh.layout = (CheckableLinearLayout)itemView.findViewById(R.id.layout); itemView.setTag(vh); } else { vh = (ViewHolder)itemView.getTag(); } final ExpandableListView listView = ((ExpandableListView)((MainActivity)context).findViewById(R.id.list)); final int position = listView.getFlatListPosition(ExpandableListView.getPackedPositionForChild(groupPosition, childPosition)); listView.setItemChecked(position, checkedState[groupPosition][childPosition]); vh.layout.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { ((CheckableLinearLayout)v).toggle(); checkedState[groupPosition][childPosition] = !checkedState[groupPosition][childPosition]; listView.setItemChecked(position, ((CheckableLinearLayout)v).isChecked()); } }); return itemView; } ... } 

带有多选的ExpandableListView。 在API 4.3和4.0.3上testing此代码也可以正确处理更改屏幕方向。 阻塞组通过SparseBooleanArray使所选元素正常工作。

我希望这个示例代码将帮助:)

活动

 ExpandableListView list; ArrayList<YouCat> cat = new ArrayList<YouCat>(); 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<YouCat>) savedInstanceState.getSerializable("cat"); Type selType = new TypeToken<SparseBooleanArray>() {}.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()); } 

适配器

 public class YouAdapter extends BaseExpandableListAdapter{ private Context context; private List<YouCat> mGroupCollection; private ExpandableListView mExpandableListView; public YouAdapter(Context context, ExpandableListView pExpandableListView, List<YouCat> 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<YouCat> 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类

 public class YouCat implements Serializable { private static final long serialVersionUID = 2070450081971040619L; public String name = null; public boolean selected = false; public ArrayList<YouSubCat> sub = new ArrayList<YouSubCat>(); } 

YouSubCat类

 public class YouSubCat implements Serializable { private static final long serialVersionUID = -1487507723105914936L; public String name = null, desc = null; public boolean selected = false; } 

子行布局

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" > <CheckBox android:id="@+id/myCheckBox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:clickable="false" android:focusable="false" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_marginLeft="10dp" android:layout_toRightOf="@+id/myCheckBox" android:text="TextView" android:textAppearance="?android:attr/textAppearanceLarge" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/textView1" android:layout_alignParentRight="true" android:layout_below="@+id/textView1" android:text="TextView" /> </RelativeLayout> 

组布局

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="8dp" > <TextView android:id="@+id/text1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft" android:textAppearance="?android:attr/textAppearanceMedium" /> </LinearLayout> 

获取选定的子项目

 final SparseBooleanArray checkedItems = list.getCheckedItemPositions(); for (int i = 0; i < checkedItems.size(); i++) { if(checkedItems.valueAt(i)) data = ((String)list.getItemAtPosition(checkedItems.keyAt(i))); } 

带有checkbox的可扩展ListView

我们可以在保持可扩展列表的checkbox状态的github中获得完整的示例。

点击链接获取Android studio项目
https://github.com/bhat-dinesh/ExpandableListViewWithCheckBox

我希望这有帮助 :)