转自: http://blog.csdn.net/zxt0601/article/details/53389835
概述
本文是这个系列的第三篇,不出意外也是终结篇。因为使用经过重构后的控件已经可以快速实现市面上带 索引导航、悬停分组的列表界面了。
在前两篇里,我们从0开始,一步一步实现了仿微信通讯录、饿了么选餐界面。
(第一篇戳我 第二篇戳我)
这篇文章作为终结篇,和前文相比,主要涉及以下内容:
* 重构悬停分组,将TitleItemDecoration更名为SuspensionDecoration,数据源依赖ISuspensionInterface接口。
* 重构索引导航,将IndexBar对数据源的操作,如排序,转拼音等分离出去,以接口IIndexBarDataHelper通信。
* 有N多兄弟给我留言、加QQ问的:如何实现美团选择城市列表页面,
* 添加一个不带悬停分组的HeaderView(微信通讯录界面)
代码传送门:喜欢的话,随手点个star。多谢
https://github.com/mcxtzhang/SuspensionIndexBar
老规矩,先上图:
。
(SwipeDelMenuLayout : https://github.com/mcxtzhang/SwipeDelMenuLayout)
本文将先举例子如何写,并对其中涉及到的重构部分进行讲解。
如有不明者,建议先观看(第一篇戳我 第二篇戳我),
以及下载Demo,边看代码边阅读,效果更佳。
转载请标明出处:
http://blog.csdn.net/zxt0601/article/details/53389835
本文出自:【张旭童的博客】(http://blog.csdn.net/zxt0601)
代码传送门:喜欢的话,随手点个star。多谢
https://github.com/mcxtzhang/SuspensionIndexBar
微信通讯录界面写法
先从简单的用法看起,微信通讯录界面和普通的 分组悬停&索引导航 的列表相比:
* 多了四个HeaderView
* 这些HeaderView布局和主体Item一样
* 这些HeaderView 没有分组悬停title
* 这些HeaderView是一组的,索引title自定义
实现:
HeaderView不是本文讨论重点,随意实现之。我用的是我自己之前写的,戳我
布局和主体Item一致
由于布局一致,则我们肯定偷懒直接用主体Item的Bean,将city设置为相应的数据即可,如 “新的朋友”:
- 1
- 2
- 1
- 2
没有分组悬停
去掉分组悬停,我们需要重写isShowSuspension()
方法,返回false。
索引title自定义
它们是一组的,则索引title一致,且需要自定义。
四个头部的Bean调用setBaseIndexTag()
方法,set自定义的title,且一致即可。
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
核心代码:
在CityBean
里引入一个字段 isTop
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
初始化:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
数据加载:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
涉及到的重构代码
上文提到,重构后,SuspensionDecoration
数据源依赖的接口是ISuspensionInterface
,
如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
在BaseIndexBean
里实现,默认显示悬停,分组title和IndexBar的Tag是一样的。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
而BaseIndexPinyinBean
类,现在如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
所以我们需要实现微信那种效果,只需要重写isShowSuspension()
和isNeedToPinyin()
这两个方法,并setBaseIndexTag()
直接设置tag即可。
仿美团选择城市
这个页面还是挺麻烦的,所以步骤也最多。建议结合代码阅读Demo及库地址。
分析美团选择城市列表:
* 主体部分仍旧是一个普通的 分组悬停&索引导航 的列表(美团没有悬停功能)。
* 头部是由若干复杂HeaderView组成。
* 从右侧索引栏可以看出,定位、最近、热门这三个Item对应了列表三个HeaderView。
* 最顶部的HeaderView是不需要分组,也不需要索引的。
那么逐一实现:
主体部分
很简单,根据前文最后的封装( 第二篇戳我),如果只有主体部分,我们需要让主体部分的JavaBean继承自BaseIndexPinyinBean
,然后正常构建数据,最终设置给IndexBar和SuspensionDecoration即可。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
头部若干HeaderViews
这里不管是通过HeaderView添加进来头部布局,还是通过itemViewType自己去实现,核心都是通过itemViewType去做的。
也就是说头部的HeaderView也是RecyclerView的Item。
既然是Item一定对应着相应的JavaBean。
我们需要针对这些JavaBean让其分别继承BaseIndexPinyinBean
。
具体怎么实现头部布局不是本文重点,不再赘述,Demo里有代码可细看Demo及库地址。
定、近、热三个HeaderView的处理
定、近、热三个HeaderView有如下特点:
* 右侧导航索引的title 为自定义,不是拼音首字母则也不需要排序。
* 悬停分组的title 和 右侧导航索引的title 不一样,则悬停分组的title也需要自定义。
做法:
不过既然是RecyclerView里的Item,又有 悬停分组、索引导航 特性。那么就要继承BaseIndexPinyinBean
。
* 不需要转化成拼音且不排序,则重写isNeedToPinyin()
返回false,并调用setBaseIndexTag(indexBarTag)
给右侧索引赋值。
* 需要自定义悬停分组的title,则重写getSuspensionTag()
返回title。
- 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
- 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
用private List<MeituanHeaderBean> mHeaderDatas;
保存定、近、热头部数据源,最终需要将其设置给IndexBar
和SuspensionDecoration
。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
最顶部的HeaderView
最顶部的HeaderView,由于不需要右侧索引,也没有悬停分组。它只是一个普通的HeaderView即可。
对于这种需求的HeaderView,只需要将它们的数量传给IndexBar
和SuspensionDecoration
即可。
在内部我已经做了处理,保证联动坐标和数据源下标的正确。
- 1
- 2
- 1
- 2
这里用headerView一共的count=4,减去上步中mHeaderDatas
的size =3,得出不需要右侧索引,也没有悬停分组 头部的数量。
将主体数据集和头部数据集合并
我们前几步中,设计到了三部分数据集,
一部分是主体数据集,
- 1
- 2
- 1
- 2
第二部分是需要特性的头部数据集
- 1
- 2
- 1
- 2
第三部分是不需要特性的数据集,这里忽略。我们只用到它的count。
我们需要将第一和第二部分融合,并且设置给IndexBar
和SuspensionDecoration
。
则我们利用它们共同的基类,BaseIndexPinyinBean
来存储。
核心代码如下:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
设置给IndexBar
:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
设置给SuspensionDecoration
:
- 1
- 2
- 1
- 2
效果图如文首。
核心代码
这里再提一点,我已经将排序功能抽离至IndexBar
的IIndexBarDataHelper
类型变量中去做,
在mIndexBar.setmSourceDatas(mSourceDatas)
时会自动排序。
也可以手动调用mIndexBar.getDataHelper().sortSourceDatas(mBodyDatas);
排序。
像本节的案例,可以选择先排序bodyDatas,然后再合并至sourceDatas,最终设置给IndexBar
和SuspensionDecoration
。
如:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
涉及到的重构代码:
除了上节提到的那些数据结构的重构,
我还将以前在IndexBar里完成的:
* 1 将汉语转成拼音
* 2 填充indexTag
* 3 排序源数据源
* 4 根据排序后的源数据源->indexBar的数据源
抽成一个接口表示,与IndexBar分离。
- 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
- 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
IndexBar内部持有这个接口的变量,调用其中方法完成需求:
- 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
- 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
我在sortSourceDatas()
实现里,已经调用了convert(datas);
和 fillInexTag(datas);
- 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
- 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
通过如下变量控制,是否需要排序,是否需要提取索引:
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
好处
这样做的好处是,当你不喜欢我这种排序方式,亦或你想自定义特殊字符的索引,现在是”#”,你都可以通过继承重写IndexBarDataHelperImpl
类的方法来完成。或者干脆实现IIndexBarDataHelper
接口,这就能满足扩展和不同的定制需求,不用每次修改IndexBar类。
总结
灵活重写ISuspensionInterface
接口中的方法,可控制:
* 是否需要显示悬停title
* 悬停显示的titles
灵活重写BaseIndexPinyinBean
中的方法,可控制:
* 是否需要被转化成拼音, 类似微信头部那种就不需要 美团的也不需要
* 微信的头部 不需要显示索引
* 美团的头部 索引自定义
* 默认应该是需要的
* 在isNeedToPinyin()
返回false时,不要忘了手动setBaseIndexTag()
设置IndexBar的Tag值.
IndexBar
的IIndexBarDataHelper
都提供了setHeaderViewCount(int headerViewCount)
方法,供设置 不需要右侧索引,也没有悬停分组的HeaderView数量。
推荐文章
4、如何自学Android, 教大家玩爆Android(成为大神必看)
5、2016 Google hosts 持续更新【更新 于:2016-08-27】(免费翻墙必备)
8、Android Studio 2.2 正式起航(玩爆Android Studio 2.2必备)
Android Studio 2.2 新功能实例代码:
Android Studio 2.2新功能实例源码(玩爆Android Studio 2.2必备)
Android Studio 2.2新功能介绍:
What's new in Android development tools - Google I/O 2016(YouTube视频需要自备梯子)
【GitHub】https://github.com/xiaole0310
【csdn博客】http://blog.csdn.net/xiaole0313
【新浪微博】http://weibo.com/u/5439466748
【知乎】http://www.zhihu.com/people/yang-shou-le
【简书】http://www.jianshu.com/users/1a47e8afa34a
【技术群】279126311 [满]
【技术群】484572225 [未]
【Email】ysle0313@gmail.com
Android Studio 2.2 新功能实例代码:
Android Studio 2.2新功能实例源码(玩爆Android Studio 2.2必备)
如果你有好的文章想和大家分享,欢迎投稿,直接向我投递文章链接即可。
欢迎扫描关注我们的微信公众号(ysle_0313),不要错过每一篇干货~
一键关注我们微信公众号 ysle_0313