最快的Android TreeView出现了!

源码地址:https://github.com/niugao/RecyclerListTreeView

  • 基于RecyclerView实现。
  • 存储数据的结构并不是Tree,而是一个ArrayList。与所有已知的网上的实现都不一样,大家似乎都跳不出固定思维。 可以比较一下代码量,此实现比其它的少一半都不止。
  • 核心是一个表示Tree的类,但它的本质是一个List。对RecyclerView没有任何改动,对Adapter只有少量封装, 使用者不会产生任何陌生感。也就是说你对RecyclerView能做的,现在依然能做。
  • 以List的形式表式树,带来很多好处:
    – 没有了递归。该用递归的地方全部变成了循环(Tree不论有多少层都没有栈溢出)。
    – 其次是有序,插入节点时,可以指定它是它爸爸的第几个儿子。
    – 极其适合在RecyclerView中使用。
    – 跟List无异,无论根节点还是子节点都对应RecyclerView中的一行。
    – 不需对RecyclerView做任何改动。

有诗为证

远看像棵树
近看不是树
似树而非树
是为牛逼树

示例

在Gradle中添加依赖:

compile ‘com.niuedu:recyclerlisttreeview:0.1.0’

Adapter:

public class ExampleListTreeAdapter extendsListTreeAdapter<ExampleListTreeAdapter.BaseViewHolder> {//行上弹出菜单的侦听器private PopupMenu.OnMenuItemClickListener itemMenuClickListener;//记录弹出菜单是在哪个行上出现的private ListTree.TreeNode currentNode;//保存子行信息的类public static class ContactInfo{//头像,用于设置给ImageView。private Bitmap bitmap;//标题private String title;//描述private String detail;public ContactInfo(Bitmap bitmap, String title, String detail) {this.bitmap = bitmap;this.title = title;this.detail = detail;}public Bitmap getBitmap() {return bitmap;}public String getTitle() {return title;}public String getDetail() {return detail;}}//构造方法public ExampleListTreeAdapter(ListTree tree,PopupMenu.OnMenuItemClickListener listener){super(tree);this.itemMenuClickListener=listener;}public ListTree.TreeNode getCurrentNode() {return currentNode;}@Overrideprotected BaseViewHolder onCreateNodeView(ViewGroup parent, int viewType){View view = null;LayoutInflater inflater = LayoutInflater.from(parent.getContext());BaseViewHolder vh;//创建不同的行Viewif(viewType==R.layout.contacts_group_item){//最后一个参数必须传trueview = inflater.inflate(viewType,parent,true);vh=new GroupViewHolder(view);}else if(viewType == R.layout.contacts_contact_item){view = inflater.inflate(viewType,parent,true);vh=new ContactViewHolder(view);}else{return null;}return vh;}@Overrideprotected void onBindNodeViewHolder(BaseViewHolder holder, int position) {View view = holder.itemView;//get node at the positionListTree.TreeNode node = tree.getNodeByPlaneIndex(position);if(node.getLayoutResId() == R.layout.contacts_group_item){//group nodeString title = (String)node.getData();GroupViewHolder gvh= (GroupViewHolder) holder;gvh.textViewTitle.setText(title);gvh.textViewCount.setText("0/"+node.getChildrenCount());gvh.aSwitch.setChecked(node.isChecked());gvh.aSwitch.setTag(node);gvh.textViewMenu.setTag(node);}else if(node.getLayoutResId() == R.layout.contacts_contact_item){//child nodeContactInfo info = (ContactInfo) node.getData();ContactViewHolder cvh= (ContactViewHolder) holder;cvh.imageViewHead.setImageBitmap(info.getBitmap());cvh.textViewTitle.setText(info.getTitle());cvh.textViewDetail.setText(info.getDetail());cvh.aSwitch.setChecked(node.isChecked());cvh.aSwitch.setTag(node);}}//组行和联系人行的Holder基类class BaseViewHolder extends ListTreeViewHolder{public BaseViewHolder(View itemView) {super(itemView);}}//将ViewHolder声明为Adapter的内部类,反正外面也用不到class GroupViewHolder extends BaseViewHolder {TextView textViewTitle;TextView textViewCount;Switch aSwitch;TextView textViewMenu;public GroupViewHolder(View itemView) {super(itemView);textViewTitle = itemView.findViewById(R.id.textViewTitle);textViewCount = itemView.findViewById(R.id.textViewCount);aSwitch = itemView.findViewById(R.id.switchChecked);textViewMenu = itemView.findViewById(R.id.textViewMenu);//应响应点击事件而不是CheckedChange事件,因为那样会引起事件的递归触发aSwitch.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {ListTree.TreeNode node = (ListTree.TreeNode) view.getTag();node.setChecked(!node.isChecked());int planeIndex = tree.getNodePlaneIndex(node);//改变所有的子孙们的状态int count =tree.setDescendantChecked(planeIndex,node.isChecked());notifyItemRangeChanged(planeIndex,count+1);}});//点了PopMenu控件,弹出PopMenutextViewMenu.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {ListTree.TreeNode node = (ListTree.TreeNode) v.getTag();currentNode=node;PopupMenu popup = new PopupMenu(v.getContext(), v);popup.setOnMenuItemClickListener(itemMenuClickListener);MenuInflater inflater = popup.getMenuInflater();inflater.inflate(R.menu.menu_item, popup.getMenu());popup.show();}});}}class ContactViewHolder extends BaseViewHolder{ImageView imageViewHead;TextView textViewTitle;TextView textViewDetail;Switch aSwitch;public ContactViewHolder(View itemView) {super(itemView);imageViewHead = itemView.findViewById(R.id.imageViewHead);textViewTitle = itemView.findViewById(R.id.textViewTitle);textViewDetail = itemView.findViewById(R.id.textViewDetail);aSwitch = itemView.findViewById(R.id.switchChecked);//应响应点击事件而不是CheckedChange事件,因为那样会引起事件的递归触发aSwitch.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {ListTree.TreeNode node = (ListTree.TreeNode) view.getTag();node.setChecked(!node.isChecked());int planeIndex = tree.getNodePlaneIndex(node);//改变所有的子孙们的状态int count =tree.setDescendantChecked(planeIndex,node.isChecked());notifyItemRangeChanged(planeIndex,count+1);}});}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180

使用Adapter

public class MainActivity extends AppCompatActivityimplements PopupMenu.OnMenuItemClickListener {//保存数据的集合private ListTree tree=new ListTree();//从ListTreeAdapter派生的AdapterExampleListTreeAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);setSupportActionBar(toolbar);//使用Android原生的RecyclerView即可RecyclerView listView = findViewById(R.id.listview);//创建后台数据:一棵树//创建组们,是root node,所有parent为nullListTree.TreeNode groupNode1=tree.addNode(null,"特别关心", R.layout.contacts_group_item);ListTree.TreeNode groupNode2=tree.addNode(null,"我的好友", R.layout.contacts_group_item);ListTree.TreeNode groupNode3=tree.addNode(null,"朋友", R.layout.contacts_group_item);ListTree.TreeNode groupNode4=tree.addNode(null,"家人", R.layout.contacts_group_item);ListTree.TreeNode groupNode5=tree.addNode(null,"同学", R.layout.contacts_group_item);//第二层ExampleListTreeAdapter.ContactInfo contact;Bitmap bitmap= BitmapFactory.decodeResource(getResources(), R.drawable.contacts_normal);contact = new ExampleListTreeAdapter.ContactInfo(bitmap,"王二","[在线]我是王二");ListTree.TreeNode contactNode1=tree.addNode(groupNode2,contact,R.layout.contacts_contact_item);ListTree.TreeNode contactNode2=tree.addNode(groupNode5,contact,R.layout.contacts_contact_item);//再添加一个bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.contacts_normal);contact=new ExampleListTreeAdapter.ContactInfo(bitmap,"王三","[离线]我没有状态");tree.addNode(groupNode2,contact,R.layout.contacts_contact_item);tree.addNode(groupNode5,contact,R.layout.contacts_contact_item);//第三层bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.contacts_normal);contact=new ExampleListTreeAdapter.ContactInfo(bitmap,"东邪","[离线]出来还价");ListTree.TreeNode n=tree.addNode(contactNode1,contact,R.layout.contacts_contact_item);n.setShowExpandIcon(false);//再添加一个bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.contacts_normal);contact=new ExampleListTreeAdapter.ContactInfo(bitmap,"李圆圆","[离线]昨天出门没出去");n=tree.addNode(contactNode1,contact,R.layout.contacts_contact_item);n.setShowExpandIcon(false);adapter=new ExampleListTreeAdapter(tree,this);listView.setLayoutManager(new LinearLayoutManager(this));listView.setAdapter(adapter);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.menu_main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {int id = item.getItemId();//noinspection SimplifiableIfStatementif (id == R.id.action_settings) {return true;}else if(id == R.id.action_del_selected){//删除选中的Nodes,删一个Node时会将其子孙一起删掉tree.removeCheckedNodes();adapter.notifyDataSetChanged();return true;}return super.onOptionsItemSelected(item);}@Overridepublic boolean onMenuItemClick(MenuItem item){switch (item.getItemId()) {case R.id.action_add_item://向当前行增加一个儿子ListTree.TreeNode node = adapter.getCurrentNode();Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.contacts_normal);ExampleListTreeAdapter.ContactInfo contact=new ExampleListTreeAdapter.ContactInfo(bitmap,"New contact","[离线]我没有状态");ListTree.TreeNode childNode = tree.addNode(node,contact,R.layout.contacts_contact_item);adapter.notifyTreeItemInserted(node,childNode);return true;default:return false;}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96




转自:http://blog.csdn.net/niu_gao/article/details/78985540

最快的Android TreeView出现了!相关推荐

  1. 比真机还快的Android模拟器——Genymotion

    比真机还快的Android模拟器--Genymotion                                                     ----转载请注明出处:coder-p ...

  2. 金山快盘 android,金山快盘Android新版正式上线 重视用户体验更便捷

    金山快盘于5月26日发布以来,掀起了同步网盘的一轮热潮.而高效快捷的多同步终端也一直是金山快盘得人心的一大原因,今日,金山快盘团队经过一系列的研发测试,快盘Android最新版本1.7版正式上线. 金 ...

  3. 金山快盘 android,随时随地的存储 金山快盘Android版评测

    [IT168 评测]8月4日,金山快盘Android版继6月1.6版本后又一次给力更新,Android版快盘是专门为Android平台用户打造的一款手机软件.配合pc版.web版快盘,真正实现了文件永 ...

  4. 库克电话会实录:iphone se比最快的Android手机还要快

    当地时间周四苹果公布2020年第二财季财报.财报显示,苹果公司当季营收583.1亿美元,相比去年同期的580.2亿美元小幅上涨1%,高于分析师此前预期的547.8亿美元:净利112.5亿美元,较去年同 ...

  5. android 快盘接口,金山快盘Android版自动备份功能详解

    近日,金山快盘Android版发布了新版本--1.9.3版,在这一版本中,小编发现了几大功能上的亮点,诸如密码锁功能.增加了常见问题答疑.优化"问题反馈"功能等,但是,新版手机快盘 ...

  6. android 快盘接口,金山快盘Android正式版今日上线

    金山快盘Android最新版本1.7版今日正式上线(TechWeb配图) [TechWeb报道]8月5日消息,网盘产品金山快盘Android正式版(1.7版本)今日宣布正式上线. 据了解,金山快盘An ...

  7. android 充电 测试,谁最快? Android Authority带来的手机充电测试

    原标题:谁最快? Android Authority带来的手机充电测试 [安卓中文网]现在快充已经是新一代手机的标配了,不少厂商在发布新机的时候多多少少都会提到这一点. Android Authori ...

  8. android 7 屏幕断电,外媒眼中的一加7 Pro:使用过最快的Android手机

    原标题:外媒眼中的一加7 Pro:使用过最快的Android手机 一加7 Pro自发布以来,距今也一个多月了,然后它的热度并没有持续降低,反而逐渐增加,在各大平台讨论的网友们依然随处可见.根本原因还是 ...

  9. 推荐一款超快的Android模拟器

    Android的原生模拟器特别的慢,Genymotion是一款非常满意.速度极快的模拟器,启动值需要几秒钟.至于如何使用可以看他们网页的介绍http://www.genymotion.com/

最新文章

  1. BGA封装芯片手工焊接攻略
  2. aix下mysql启动命令_AIX常用操作命令
  3. Apache Shiro实现用户登录功能
  4. .NET的一点历史故事:擦肩而过的机遇
  5. [2013.8.16]小议innerText/HTML以及outerText/HTML
  6. php日期分页,php – Laravel分页不适用于日期搜索
  7. c++贪吃蛇_细致的C语言写贪吃蛇教程+详细思路-适合新手附源码
  8. 收藏:常用的广告代码的表达式
  9. webservice服务器框架配置文件,基于Maven环境进行Spring集成CXF WebService框架
  10. redis mysql 雪崩_Redis雪崩和穿透问题
  11. 2019春季高考计算机试题,山东省2019春季高考模拟考试信息技术试试卷+答案(10页)-原创力文档...
  12. 细雨闲花-2007经典高考作文(绝对经典)
  13. 如何维持APP用户的登陆状态
  14. 华为sug 6000 系列防火墙端口范围映射
  15. html小总结:表格立体效果的实现.
  16. oracle asm omf,Oracle Managed Files,OMF
  17. windows中Appium-desktop配合安卓模拟器的完美使用
  18. 您不知道Android的ES File Explorer可以做的19件事
  19. R型电焊机电源变压器的特点都有哪些?
  20. Java编写猜单词游戏

热门文章

  1. 一月集 一个会写诗的程序员2019
  2. python列转行函数_python 列转行
  3. 计算机无法识别ipad,ipad连接电脑没反应怎么办 ipad air连接电脑无法识别解决办法...
  4. 2022年前端面试题整理,持续更新中
  5. 定时跑视图往另外一张表添加数据_聊一聊数据库中的锁
  6. 欢迎使用CSDN-markdown编辑器不啵啵啵啵啵啵啵啵啵啵啵啵
  7. 6月3日至5日 服务器信息维修,2015年6月3日维护公告
  8. 迄今见过最好的职业规划的文章
  9. python强制终止_python强制终止
  10. 武汉大学计算机学院期末考试时间,【通知公告】关于2018-2019学年第二学期期末考试工作安排的通知...