最快的Android TreeView出现了!
最快的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出现了!相关推荐
- 比真机还快的Android模拟器——Genymotion
比真机还快的Android模拟器--Genymotion ----转载请注明出处:coder-p ...
- 金山快盘 android,金山快盘Android新版正式上线 重视用户体验更便捷
金山快盘于5月26日发布以来,掀起了同步网盘的一轮热潮.而高效快捷的多同步终端也一直是金山快盘得人心的一大原因,今日,金山快盘团队经过一系列的研发测试,快盘Android最新版本1.7版正式上线. 金 ...
- 金山快盘 android,随时随地的存储 金山快盘Android版评测
[IT168 评测]8月4日,金山快盘Android版继6月1.6版本后又一次给力更新,Android版快盘是专门为Android平台用户打造的一款手机软件.配合pc版.web版快盘,真正实现了文件永 ...
- 库克电话会实录:iphone se比最快的Android手机还要快
当地时间周四苹果公布2020年第二财季财报.财报显示,苹果公司当季营收583.1亿美元,相比去年同期的580.2亿美元小幅上涨1%,高于分析师此前预期的547.8亿美元:净利112.5亿美元,较去年同 ...
- android 快盘接口,金山快盘Android版自动备份功能详解
近日,金山快盘Android版发布了新版本--1.9.3版,在这一版本中,小编发现了几大功能上的亮点,诸如密码锁功能.增加了常见问题答疑.优化"问题反馈"功能等,但是,新版手机快盘 ...
- android 快盘接口,金山快盘Android正式版今日上线
金山快盘Android最新版本1.7版今日正式上线(TechWeb配图) [TechWeb报道]8月5日消息,网盘产品金山快盘Android正式版(1.7版本)今日宣布正式上线. 据了解,金山快盘An ...
- android 充电 测试,谁最快? Android Authority带来的手机充电测试
原标题:谁最快? Android Authority带来的手机充电测试 [安卓中文网]现在快充已经是新一代手机的标配了,不少厂商在发布新机的时候多多少少都会提到这一点. Android Authori ...
- android 7 屏幕断电,外媒眼中的一加7 Pro:使用过最快的Android手机
原标题:外媒眼中的一加7 Pro:使用过最快的Android手机 一加7 Pro自发布以来,距今也一个多月了,然后它的热度并没有持续降低,反而逐渐增加,在各大平台讨论的网友们依然随处可见.根本原因还是 ...
- 推荐一款超快的Android模拟器
Android的原生模拟器特别的慢,Genymotion是一款非常满意.速度极快的模拟器,启动值需要几秒钟.至于如何使用可以看他们网页的介绍http://www.genymotion.com/
最新文章
- BGA封装芯片手工焊接攻略
- aix下mysql启动命令_AIX常用操作命令
- Apache Shiro实现用户登录功能
- .NET的一点历史故事:擦肩而过的机遇
- [2013.8.16]小议innerText/HTML以及outerText/HTML
- php日期分页,php – Laravel分页不适用于日期搜索
- c++贪吃蛇_细致的C语言写贪吃蛇教程+详细思路-适合新手附源码
- 收藏:常用的广告代码的表达式
- webservice服务器框架配置文件,基于Maven环境进行Spring集成CXF WebService框架
- redis mysql 雪崩_Redis雪崩和穿透问题
- 2019春季高考计算机试题,山东省2019春季高考模拟考试信息技术试试卷+答案(10页)-原创力文档...
- 细雨闲花-2007经典高考作文(绝对经典)
- 如何维持APP用户的登陆状态
- 华为sug 6000 系列防火墙端口范围映射
- html小总结:表格立体效果的实现.
- oracle asm omf,Oracle Managed Files,OMF
- windows中Appium-desktop配合安卓模拟器的完美使用
- 您不知道Android的ES File Explorer可以做的19件事
- R型电焊机电源变压器的特点都有哪些?
- Java编写猜单词游戏
热门文章
- 一月集 一个会写诗的程序员2019
- python列转行函数_python 列转行
- 计算机无法识别ipad,ipad连接电脑没反应怎么办 ipad air连接电脑无法识别解决办法...
- 2022年前端面试题整理,持续更新中
- 定时跑视图往另外一张表添加数据_聊一聊数据库中的锁
- 欢迎使用CSDN-markdown编辑器不啵啵啵啵啵啵啵啵啵啵啵啵
- 6月3日至5日 服务器信息维修,2015年6月3日维护公告
- 迄今见过最好的职业规划的文章
- python强制终止_python强制终止
- 武汉大学计算机学院期末考试时间,【通知公告】关于2018-2019学年第二学期期末考试工作安排的通知...