千家信息网

支持多项选择的ExpandableListView怎么用

发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,这篇文章主要介绍支持多项选择的ExpandableListView怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!目标(需求):1. 创建一个可展开可收缩的列表;2. 其列
千家信息网最后更新 2025年01月19日支持多项选择的ExpandableListView怎么用

这篇文章主要介绍支持多项选择的ExpandableListView怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

目标(需求):

1. 创建一个可展开可收缩的列表;

2. 其列表项包含多个checkable的部件,当选择某一行时,该行包含的checkable的部件需要作出相应的变化;

3. 可以选择多个列表项,并且这些列表项可被读出

结果图:

实现:

1. 创建主layout用于规划列表显示。对于具体的列表项,为了实现的方便我们也创建一个layout文件。

             

2. 类似ListView,ExpandableListView也是通过Adapter来管理其包含的各种元素和操作,这里我们创建一个扩展自BaseExpandableListAdapter的Adapter。与ListView不同的是,ExpandableListAdapter要渲染实现两级View(Group级和列表项级)的操作。它通过getGroupView()渲染Group项,通过getChildView()渲染列表子项。

@Override   public View getGroupView(int groupPosition, boolean isExpanded,       View convertView, ViewGroup parent) {     View groupView = convertView;     if (groupView == null) {       groupView = new TextView(context);       ((TextView)groupView).setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);       groupView.setPadding(50,0,0,0);     }     ((TextView)groupView).setText(groupData[groupPosition]);     ((TextView)groupView).setTextColor(context.getResources().getColor(R.color.fgcolor));          return groupView;   }    @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);       vh.item = (TextView)itemView.findViewById(R.id.item);       itemView.setTag(vh);     } else {       vh = (ViewHolder)itemView.getTag();     }     vh.item.setText(itemData[groupPosition][childPosition]);     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;   }

3. 为每一列表子项容器创建OnClickListener监听鼠标的点击事件。在这里要注意,由于列表子项包含了CheckBox,所以为了使点击事件不要被CheckBox捕获,我们需要创建一个扩展自CheckBox的类来屏蔽鼠标和键盘事件。同时,需要在这个容器里搜索其包含的checkable的部件并将check操作传给这些部件。

Adapter中的方法getChildView()需要实现鼠标点击监听器:

public View getChildView(final int groupPosition, final int childPosition,       boolean isLastChild, View convertView, ViewGroup parent) {   View itemView = convertView;   final ViewHolder vh; ...      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; }

扩展自CheckBox的InertCheckBox需要屏蔽键盘和鼠标事件

public class InertCheckBox extends CheckBox {   @Override   public boolean onKeyDown(int keyCode, KeyEvent event) {   //直接返回false   return false;   }    @Override   public boolean onKeyUp(int keyCode, KeyEvent event) {   //直接返回false   return false; }    @Override   public boolean onTouchEvent(MotionEvent event) {   //直接返回false   return false;   }     @Override    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {   //直接返回false   return false;   ... }

列表项容器需要实现Checkable接口并且把check操作传递给其checkable的子部件

public class CheckableLinearLayout extends LinearLayout implements Checkable { ...   @Override   public void setChecked(boolean checked) {   this.isChecked = checked;   for (Checkable view : checkableViews) {    view.setChecked(checked);    }   }      @Override   public boolean isChecked() {    return this.isChecked;   }    @Override   public void toggle() {    isChecked = !isChecked;    for (Checkable view : checkableViews)    {   view.toggle();    }   }    @Override   protected void onFinishInflate() {   super.onFinishInflate();          for (int i=0; i

开发中遇到的问题:

1. 渲染后的child view类似于放在一个cache中,下一次再通过convertView取时,由于Group的收缩或扩展操作会隐藏/显示一些child view,导致某一child View的flat position发生变化,获取到的convertView不是原来希望获取的view。所以,每次获取到view后都需要对其内容重新设置(比如设置正确文本,设置监听器等)

2. check的状态设置很tricky。我开始认为直接在监听器中调用容器的toggle()方法即可。结果发现一旦某个group做了expand或collapse操作后,所有列表项的check状态全没了。后来发现原来group做了expand/collapse操作后,ListView会对其所有子项重新设置check状态,而check状态的值是存在ListView的一个SparseBooleanArray表里(mCheckStates)。由于没有对这个表进行设置,所以一刷新check状态就全丢了。并且由于这个表的key是基于拉平后所有可见的列表项的位置定的,当group扩展或收缩后,同一个列表项,它拉平后的位置还会变化。所以,为了解决这个问题,我在adapter里增加了一个二维表用于记录每一列表项的check状态。在执行 listView的setItemChecked函数时,其check状态是从这个自己创建的表中读出的,不能通过ListView的mCheckStates来读。这个我认为是ExpandableListView的一个缺陷。

遗留的已知问题:

我使用了@drawable/checkbox 来定义checkbox check 和uncheck时的图片,但当checkbox被check上时,这个checked的图片没有生效。不知道为什么,还需要进一步debug.

以上是"支持多项选择的ExpandableListView怎么用"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

状态 部件 选择 事件 子项 容器 鼠标 监听 内容 监听器 问题 变化 收缩 支持 位置 图片 多个 方法 篇文章 结果 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 浙江网络技术服务报价 微信无法连接到服务器1237 单例 数据库 qt 登陆 网络安全不可否认性算法 软件开发中常用的指令 cf现在四个服务器能容纳多少人 50多台服务器远距离传输 app服务器型号怎么看 erp系统上云服务器配置 国家网络安全的领导者 网络安全交互广告设计 如何提升数据库的优化能力 软件开发工程考公务员难吗 软件开发公司需要多少人员 软件开发可以自己做软件吗 数据库数据导入导出实验总结 云服务器 挂载云盘 小型服务器的安全要求 图数据库数据存储方法 学网络技术应该从哪方面开始 网络安全工作动态 软件开发电子工程论文题目 软件开发中的某些观点辨析 ios多路服务器怎么用 吉林刀片服务器虚拟主机 软件开发怎么设置试用期 为什么手机充话费显示服务器开小 清远无线软件开发费用是多少 我的世界服务器网易版预告 安恒网络安全销售的待遇
0