Android快速索引条控件

效果展示

代码实现

自定义view,画出静态的图形

在canvas上指定好位置,用各种画笔Paint,重要的是分析的过程。
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
private Paint paint;
private int cellWidth, cellHeight;
private void init() {
paint = new Paint();
paint.setTextSize(40);
paint.setColor(Color.WHITE);
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (cellHeight == 0) cellHeight = getMeasuredHeight() / indexs.length;
if (cellWidth == 0) cellWidth = getMeasuredWidth();
//分别画26个字母
for (int i = 0; i < indexs.length; i++) {
//先测量用此画笔画字母的大小,用一个矩形把它包裹起来,这样方便计算字母的高度
Rect bounds = new Rect();
paint.getTextBounds(indexs[i], 0, indexs[i].length(), bounds);
//计算画每个字母的起始坐标
float x = cellWidth / 2 - paint.measureText(indexs[i]) / 2;
float y = cellHeight / 2 + bounds.height() / 2 + i * cellHeight;
canvas.drawText(indexs[i], x, y, paint);
}
}

实现onTouch事件,完成动态效果

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
private int lastIndex = -1;
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
// if (x >= 0 && x <= cellWidth) { //只对quickindexbar的触摸事件有效
// return false;
// }
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (isSameIndex(y / cellHeight)) break;
String word = indexs[((int) (y / cellHeight))];
lastIndex = y / cellHeight;
if (mIndexChangedListener != null) {
mIndexChangedListener.indexChanged(word);
}
break;
case MotionEvent.ACTION_UP:
lastIndex = -1;
break;
default:
break;
}
//自行处理触摸事件,不向上传递
return true;
}
/**
* 当前的索引位置是否和上一个相等
*
* @return
*/
private boolean isSameIndex(int currIndex) {
return lastIndex == currIndex;
}
private IndexChangedListener mIndexChangedListener;
public void setIndexChangedListener(IndexChangedListener indexChangedListener) {
mIndexChangedListener = indexChangedListener;
}
public interface IndexChangedListener {
void indexChanged(String word);
}

给触摸事件添加更加人性化的交互

QuickIndexBar交互效果的实现

在处理onTouch事件时,改变画笔的设置,画出不同的图案。

在onTouch中调用
1
2
3
//重新调用onDraw
invalidate();
在onDraw中增加下面的逻辑:
画每个元素之前先设置不同的画笔。    
1
2
3
4
5
6
7
8
if (i == lastIndex) { //正在touch的位置 需要更加人性化的交互
paint.setTextSize(60);
paint.setColor(Color.GRAY);
} else {
paint.setTextSize(40);
paint.setColor(Color.WHITE);
}

中间放大框的实现

当前Activity接受到QuickIndexBar的变化事件后,调用showIndexLabel方法,通过handler完成延迟操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private Handler mHandler = new Handler();
private void showIndexLabel(String word) {
mLabel.setVisibility(View.VISIBLE);
mLabel.setText(word);
mHandler.removeCallbacksAndMessages(null); //移除所有消息队列
mHandler.postDelayed(new Runnable() { //发送延时消息
@Override
public void run() {
mLabel.setVisibility(View.GONE);
}
}, DEFAULT_DELAY);
}

完整代码

github