最近在做关于伸缩列表这块功能,在网上找了许多关于ExpandableListView+CheckBox的例子,不是代码比较臃肿,就是写法混乱,都没什么参考意义,所以动手写了个简洁易懂的Demo.
思路:一、自定义一个adapter,继承BaseExpandableListAdapter,在该类中创建两个列表键值对存储对象,分别将位置id和boolean值存进去,在getGroupView和getChildView中调用相应的方法进行判断
二、同时也可在该类下创建接口,实现选中数据、个数回传。思路简单易理解。
源码介绍:
1、将GroupList和ChildList传入
private List<Map<Integer, Boolean>> gpList = new ArrayList<>();
private List<List<Map<Integer, Boolean>>> cdList = new ArrayList<>();
public <T> void setItemCheck(List<T> list1, List<List<T>> list2) {
gpList = new ArrayList<>();
cdList = new ArrayList<>();
for (int i = 0; i < list1.size(); i++) {
Map<Integer, Boolean> m = new HashMap<>();
m.put(i, false);
gpList.add(i, m);
Map<Integer, Boolean> map = new HashMap<>();
List<Map<Integer, Boolean>> list = new ArrayList<>();
for (int j = 0; j < list2.get(i).size(); j++) {
map.put(j, false);
list.add(j, map);
}
cdList.add(i, list);
}
}
2、全选和全不选 只需要将上面的的false改为true即可,同时要记得调用notifyDataSetChanged
public <T> void unCheckAll(List<T> list1, List<List<T>> list2) {
setItemCheck(list1, list2);
this.notifyDataSetChanged();
}
public <T> void checkAll(List<T> list1, List<List<T>> list2) {
gpList = new ArrayList<>();
cdList = new ArrayList<>();
for (int i = 0; i < list1.size(); i++) {
Map<Integer, Boolean> m = new HashMap<>();
m.put(i, true);
gpList.add(i, m);
Map<Integer, Boolean> map = new HashMap<>();
List<Map<Integer, Boolean>> list = new ArrayList<>();
for (int j = 0; j < list2.get(i).size(); j++) {
map.put(j, true);
list.add(j, map);
}
cdList.add(i, list);
}
this.notifyDataSetChanged();
}
3、在onChildClick()方法中调用改类下toggleChild方法
public void toggleChild(int groupPos, int childPos) {
if (isShowChk()) {
if (cdList.get(groupPos).get(childPos).get(childPos)) {
cdList.get(groupPos).get(childPos).put(childPos, false);
} else {
cdList.get(groupPos).get(childPos).put(childPos, true);
}
if (cdList.get(groupPos).get(childPos).containsValue(false)) {
gpList.get(groupPos).put(groupPos, false);
} else {
gpList.get(groupPos).put(groupPos, true);
}
this.notifyDataSetChanged();
}
}
3、在getChildView和geiGroupView中调用setChildChkView()和setGroupChkView()方法
注意:1、 checkBox.setFocusable(false);让checkbox失去焦点,否则onChildClick()和onGroupClick()方法不会被调用,造成不可点击的问题
2、 checkBox.setClickable(false); 让checkbox不可点击,这里要注意,为了不与onChildClick()点击事件冲突
private void toggleGroup(int groupPos) {
if (isShowChk()) {
if (gpList.get(groupPos).get(groupPos)) {
gpList.get(groupPos).put(groupPos, false);
} else {
gpList.get(groupPos).put(groupPos, true);
}
if (gpList.get(groupPos).get(groupPos)) {
for (int i = 0; i < cdList.get(groupPos).size(); i++) {
cdList.get(groupPos).get(i).put(i, true);
}
} else {
for (int i = 0; i < cdList.get(groupPos).size(); i++) {
cdList.get(groupPos).get(i).put(i, false);
}
}
this.notifyDataSetChanged();
}
}
protected void setChildChkView(int groupPos, int childPos, CheckBox checkBox) {
if (isShowChk()) {
checkBox.setVisibility(View.VISIBLE);
checkBox.setFocusable(false);
checkBox.setClickable(false);
if (cdList.get(groupPos).get(childPos).get(childPos)) {
checkBox.setChecked(true);
} else {
checkBox.setChecked(false);
}
} else {
checkBox.setVisibility(View.GONE);
}
}
protected void setGroupChkView(final int groupPos, CheckBox checkBox) {
if (isShowChk()) {
checkBox.setVisibility(View.VISIBLE);
checkBox.setFocusable(false);
checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleGroup(groupPos);
callBack.setCheckedNum(getCheckedNum());
}
});
if (gpList.get(groupPos).get(groupPos)) {
checkBox.setChecked(true);
} else {
checkBox.setChecked(false);
}
} else {
checkBox.setVisibility(View.GONE);
}
}
此实现方式不会照成过多的代码,核心逻辑易写完,易读性强,可修改性强。