前言
先看下效果吧~
功能实现疑难点分析
分析:
- 假设:控件 高度 均分成 26个 方块,方块的宽度和控件宽度相同。
- 假设:每个字母 被一个方形的单元格 贴边包裹。单元格在方块内居中。
- 每个字母的坐标(X轴、Y轴)是其左下角的位置,也就是单元格的左下角位置。
- 以 A 为例:0 索引
x轴坐标:float x = measuredWidth * 0.5f - textWidth * 0.5f (控件宽度的一半 - 单元格宽度的一半)
y轴坐标:float y = cellHeight * 0.5f + textWidth * 0.5f (控件宽度的一半 + 单元格宽度的一半)- 以 B 为例:1 索引
x轴坐标:float x = measuredWidth * 0.5f - textWidth * 0.5f (控件宽度的一半 - 单元格宽度的一半)
y轴坐标:float y = cellHeight * 0.5f + textWidth * 0.5f + i * cellHeight (控件宽度的一半 + 单元格宽度的一半 + 前面所有单元格的高度)
说明: measuredWidth - 整个自定义控件的宽度;cellHeight - 单元格的高度;textWidth - 单个字母的宽度(通过画笔可以获取)
- 26个字母的绘制,并确定每个字母的位置
部分代码示例(具体的实现还请参考Demo)
//绘制 A-Z
for (int i = 0; i < LETTERS.length; i++) {
String letter = LETTERS[i];
//计算每个字母的坐标位置,通过画笔可以获取字母的宽度:measureText()
float x = cellWidth * 0.5f - paint.measureText(letter) * 0.5f;
//获取指定字符串指定区域的宽高信息
Rect rect = new Rect();
paint.getTextBounds(letter, 0, letter.length(), rect);
//获取字母的高度
int textHeight = rect.height();
//获取字母的宽度 和 paint.measureText(letter) 结果一样
//int textWidth = rect.width();
float y = cellHeight * 0.5f + textHeight * 0.5f + i * cellHeight;
//【改变选择字母】字母被选中时,重绘字母时,改变字母状态
paint.setColor(i == currentIndex ? Color.GRAY : Color.WHITE);
canvas.drawText(letter, x, y, paint);
}
- 产生触摸事件时,确定被选中的位置
private void getCurrentIndex(MotionEvent event) {
//获取当前所处位置的-Y轴-坐标(取值可能会小于0)
float y = event.getY();
//得到当前触摸位置是第几个索引位置
int index = (int) (y / cellHeight);
//获取当前索引和上次获取索引对比,相同则不处理
if (index != currentIndex) {
if (index >= 0 && index < LETTERS.length) {
currentIndex = index;
//设置一个监听回调:返回当前被选中的字母(也可以处理其他业务)
if (updateListener != null) {
updateListener.onLetterUpdate(LETTERS[index]);
}
}
}
}
- 在 activity 中监听回调,并把 listView 和 自定义控件结合起来
@Override
public void onLetterUpdate(String letter) {
showCustomToast(letter); //自定义的一个Toast(可以查看Demo)
//触摸监听回调
//找到数据集合中首次出现letter的索引位置,listView直接跳到该索引位置
for (int index = 0; index < persons.size(); index++) {
String pin = persons.get(index).getNamePinYin().charAt(0) + "";
if (TextUtils.equals(pin, letter)) {
listView.setSelection(index);
break;
}
}
}
PS:好了,到这里,一个简单的自定义快速索引功能就实现了。很高兴能在这里和大家分享以及互相学习。