快速索引在应用中很常见,在联系人,微信,省市列表,应用管理,文件管理等应用场景都可以看到快速索引的身影,本篇博客将讲解快速索引的自定义,从中你可以学到获取汉字首字母的方法,绘制字母时,纵坐标的计算方法
1. 静态绘制
1.1 初始化数据
创建自定义控件QuickIndexBar 继承View
|
|
- 第3-6 行初始化字母数组
- 第7-12 行串连构造方法
- 第15-21 行初始化画笔
- 第27 行画文字的方法
将QuickIndexBar 布局到activity_main.xml 中
|
|
1.2 计算字母坐标
画文字的x,y 坐标是文字左下角的位置
- 第一个字母的x 坐标则等于单元格宽度的一半减去文字宽度的一半,由于所有字母离左边的距离
一样,所以x 不变int x = cellWidth/2 - textWidth/2 - 第一个字母的y 坐标则等于单元格高度的一半加上文字,第二个字母需要加上一个单元格的宽度
由此类推int y = cellHeight/2 +textHeight/2 +i*cellHeight - 单元格cellWidth 为QuickIndexBar 宽度,cellHeight 为QuickIndexBar 高度/字母数组的长度
|
|
- 第19-26 行获取单元的宽高,注意单元格高度需要用float 类型
- 第8-12 行通过paint 测量文字的宽高,并计算出每个字母的坐标
2. Android drawText获取text宽度的三种方式
原文链接:http://blog.csdn.net/chuekup/article/details/7518239
3. 响应触摸事件
重写onTouchEvent()方法,解析触摸事件
|
|
- 第12 行通过触摸的y 值计算按下字母的索引值
- 第19 行记录上次按下字母的索引值,通过判断上次按下字母的索引与本次按下字母的索引是否相同,如果不同才弹出toast,避免在同一个字母上来回移动也一直弹出toast
- 第38 行手指抬起需要将lastIndex 还原为初始值
- 第45 行一定要返回true,代表事件已被消费
- 第17 行是单例Toast
|
|
4. 监听回调
定义监听回调接口
|
|
在弹出Toast 的地方替换成调用接口方法
|
|
- 第14-16 调用回调接口方法,通知外面当前触摸的字母
- 第30-32 调用回调接口方法,通知外面当前触摸的字母
主Activity 中给QuickIndexBar 设置回调监听
|
|
5. 根据拼音排序
5.1.1 创建PinyinUtil.java
GitHub上有可以将汉字转拼音的开源项目,TinyPinyin,pinyin4j
- TinyPinyin:https://github.com/promeG/TinyPinyin
- pinyin4j:https://github.com/belerweb/pinyin4j
汉字转拼音需要导入pinyin4j-2.5.0.jar
|
|
5.1.2 填充ListView
用于填充ListView 的姓名数组
|
|
将姓名转化为HaoHan 对象
|
|
第24-27 行实现Comparable 接口,用于排序操作
activity_main.xml 中添加ListView
|
|
为ListView 创建数据适配器
ListView 条目的布局item_person.xml,每一个条目上都加上显示首字母的TextView
|
|
数据适配器代码
|
|
6. 根据首字母分组
6.1 修改数据适配器的getView()方法
|
|
第16-32 行如果是第一行直接显示首字母条目,如果不是第一行判断当前首字母和上一个条目的首字母是否一致, 不一致时候显示,一致则隐藏
7. ListView 和自定义控件结合
修改回调接口代码,for 循环persons 集合找到与传回来的letter 值相同的索引值,ListView 直接滚动到对应位置即可
8. 细节优化置
置为当前选中的字母
|
|
第46 行为新增代码,此时lastIndex 为当前按下的字母索引,调用一次invalidate()方法,会再次调用onDraw()方法,在onDraw()方法中通过判断lastIndex 的值,把当前按下的字母置为灰色
|
|
第13-18 行如果当前字母的索引是选中的,则将画笔颜色改为灰色,没有选中的将画笔改为白色
把回调方法中Toast 的显示方式改为TextView 显示
|
|
- 第11-21 行在屏幕中间添加一个提示框,默认情况为不显示
- 第16 行提示框的背景文件,需要在res 下新建一个drawable 文件夹,将shape_tv_center.xml 放在此文件夹下
|
|
修改回调接口中字母提示方式
|
|
- 第6-8 行将Toast 提示改为文本框提示
- 第28-36 行用消息机制延迟隐藏文本提示框,如果快速滑动showLetter()方法会频繁调用,会有多个延迟任务在消息队列中,其实当前延迟任务之前的任务都是没有必要执行的,所以可以先移除队列中所有的任务再将本次任务添加到队列中
QuickIndexBar
|
|
MainActivity
|
|
HaoHanAdapter
|
|
FancyListIndexer
|
|