公司项目中有一个选择联系人的界面,一看里面关系极其复杂,最多时有5层关系嵌套,层数还不一定,有的是第五级是人员,有的是第四级是人员,崩溃中……原来的实现方式是分了三个Activity去分别加载,个人觉得太过臃肿麻烦,选个人要调四次页面,太繁琐了。就想能不能把它整到一个页面中去,既能全选所有人又能实现单选几个人。
刚开始尝试着用 ExpandableListView 实现,效果是实现了但全选状态传递不好弄,如何点击某一层节点,让它的所有孩子都选中?整了半天没整好。心想这轮子肯定有人造过了,本着不重复造轮子的理念,去网上找找看吧。
看了 n 篇文章后,总结一下就是两种解决方案,一种是用 ExpandableListView 实现,还没有见到有案例实现全选的。另一种是直接用 ListView 实现 n 级嵌套,还能全选全不选!就第二种了。
用 ListView 实现的文章几乎所有案例都参照了 鸿神 的那篇 Android 打造任意层级树形控件 考验你的数据结构和设计, 默默的献上膝盖~
鸿神的这篇文章大概看了下,因为后面有很多人都在这个基础上做的优化,原理也写的很详细,索性直接研究后者吧。几经筛选最终挑出了这篇:更快实现Android多级树形选择列表
借鉴了上面的经验之后,顺利的做了出来。
先上图:
实现原理我就不多说啦,上面两篇文章里都讲的很清楚了。简单来讲就是把所有节点都当成一个 Node 对象,Node 对象里有该节点的 id, 它的父节点的 id:pId, 它所有子节点的 list 集合: children, 该节点的层级 level 等等。在设置数据的时候就对数据进行处理,把层级关系排好,按层级依次显示。当选中某个节点时,将它的父节点设置为选中,再将它的所有子节点循环一遍都设置为选中,就解决了全选问题。
本案例中我将选择联系人的操作封装到了一个 Activity 里面,用的时候很简单,只需启动 Activity 的时候传两个参数就可以:
Intent intent = new Intent(this, SelectReceiverActivity.class); //要请求的数据类型,将项目中用到的类型都封装到枚举类 ReceiverType 里 intent.putExtra("type", ReceiverType.TEACHER); //本次请求的标记,用于当一个页面要多次调用选人界面时,拿到选择结果的时候做区分 intent.putExtra("flag", "record"); startActivity(intent); 123456
选择的结果通过 EventBus 传递,不了解 EventBus 的请自行补习~
EventBus 的接收事件
@Subscribe(threadMode = ThreadMode.MAIN) public void onEvent(SelectReceiverEvent event){ String flag = event.getFlag();/* 如果没传flag可省去判空操作,也可省去判断flag的操作 直接根据需要对数据进行处理 */ if(flag == null){ return; } if(TextUtils.equals("flag1", flag)){ //你自己的操作 }else if(TextUtils.equals("flag2", flag)){ //你自己的操作 } }
123456789101112131415161718温馨提示:下面的代码可直接复制到你的项目中,根据需要进行删改。手把手教你怎么快速集成到项目中。
先偷个懒,为了能直接用 zhangke3016 的四个工具类,先建个跟他项目一样的包:com.multilevel.treelist,然后将 Node.java , OnTreeNodeClickListener.java , TreeHelper.java , TreeListViewAdapter.java 四个类直接拷到这个包下。

上代码
工具类篇跟业务关系不大,可直接拷贝
Node.java
这是节点对象,里面封装了能用到的所有信息,是多级列表的核心类
package com.multilevel.treelist; import java.util.ArrayList; import java.util.List; public class Node<T,B> { /** * 传入的实体对象 */ public B bean; /** * 设置开启 关闭的图片 */ public int iconExpand=-1, iconNoExpand = -1; private T id; /** * 根节点pId为0 */ private T pId ; private String name; /** * 当前的级别 */ private int level; /** * 是否展开 */ private boolean isExpand = false; private int icon = -1; /** * 下一级的子Node */ private List<Node> children = new ArrayList<>(); /** * 父Node */ private Node parent; /** * 是否被checked选中 */ private boolean isChecked; /** * 是否为新添加的 */ public boolean isNewAdd = true; /** * 该分组下的人数 */ private int count; /** * 是否是人,1=true, 0=false */ private int isPeople; public boolean isChecked() { return isChecked; } public void setChecked(boolean isChecked) { this.isChecked = isChecked; } public Node() {} public Node(T id, T pId, String name) { super(); this.id = id; this.pId = pId; this.name = name; } public Node(T id, T pId, String name, B bean) { super(); this.id = id; this.pId = pId; this.name = name; this.bean = bean; } public Node(T id, T pId, String name, int count) { this.id = id; this.pId = pId; this.name = name; this.count = count; } public Node(T id, T pId, String name, int count, int isPeople) { this.id = id; this.pId = pId; this.name = name; this.count = count; this.isPeople = isPeople; } public int getIcon() { return icon; } public void setIcon(int icon) { this.icon = icon; } public T getId() { return id; } public void setId(T id) { this.id = id; } public T getpId() { return pId; } public void setpId(T pId) { this.pId = pId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void setLevel(int level) { this.level = level; } public boolean isExpand() { return isExpand; } public List<Node> getChildren() { return children; } public void setChildren(List<Node> children) { this.children = children; } public Node getParent() { return parent; } public void setParent(Node parent) { this.parent = parent; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public int getIsPeople() { return isPeople; } public void setIsPeople(int isPeople) { this.isPeople = isPeople; } /** * 是否为跟节点 * * @return */ public boolean isRoot() { return parent == null; } /** * 判断父节点是否展开 * * @return */ public boolean isParentExpand() { if (parent == null) return false; return parent.isExpand(); } /** * 是否是叶子界点 * * @return */ public boolean isLeaf() { return children.size() == 0; } /** * 获取level */ public int getLevel() { return parent == null ? 0 : parent.getLevel() + 1; } /** * 设置展开 * * @param isExpand */ public void setExpand(boolean isExpand) { this.isExpand = isExpand; if (!isExpand) { for (Node node : children) { node.setExpand(isExpand); } } } @Override public String toString() { return "Node{" + "id=" + id + ", pId=" + pId + ", name='" + name + ''' + ", level=" + level + ", isPeople=" + isPeople + ", count=" + count +
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244相关知识
jQuery MiniUI 开发教程 树形控件 创建树:树形结构(一)
基于Android Studio如何实现 购物商城 案例(简单易上手)
虚拟树形选择器 vTree
Android 移动开发
Android Studio实现简单的购物商城界面
安装android NDK详细记录
【朝花夕拾】Android性能篇之(六)Android进程管理机制
Android进阶之路
Android WebView 拍照和选择图片
Android Sunflower 带您玩转 Jetpack
网址: Android多级树形选择列表案例 https://m.huajiangbk.com/newsview2489516.html
| 上一篇: layui 树形下拉框(单选)基 |
下一篇: vue+elementui封装s |