現在在許多的應用都用到了索引的自定義View,如微信的聯繫人檢索,大衆點評的城市列表檢索等等。它的實現原理無非就是在一個View上面從上到下依次排列畫出,並提供一個接口以便於快速導航。下面爲實現代碼:
package com.example.quubee.view;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
/**
* 字母快速導航自定義View
*
* @author mm
*
*/
public class MyLetterView extends View {
private Paint paint;
private List<String> letters;
private OnTouchLetterListener listener;
public MyLetterView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
/**
* 做初始化操作
*/
private void initView() {
// 初始化畫筆
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.GRAY);
// 初始化要顯示的數據,這裏是26個大寫的英文字母
letters = new ArrayList<String>();
for (int i = 65; i < 91; i++) {
letters.add(String.valueOf((char) i));
}
// 設置字體大小
paint.setTypeface(Typeface.MONOSPACE);
paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
13, getResources().getDisplayMetrics()));
}
/**
* 重新繪製
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 獲取整個View的寬和高
int width = getWidth();
int height = getHeight();
// 計算文字所佔的高度
int letterHeight = height / letters.size();
// 開始繪製
for (int i = 0; i < letters.size(); i++) {
// 獲取文字的邊界屬性
Rect bounds = new Rect();
paint.getTextBounds(letters.get(i), 0, letters.get(i).length(),
bounds);
int lWidth = bounds.width();
int lHeight = bounds.height();
// 計算文字繪製的座標點,一般在左下角
float x = (width - lWidth) / 2;
float y = (letterHeight - lHeight) / 2 + letterHeight * i;
canvas.drawText(letters.get(i), x, y, paint);
}
}
/**
* 處理觸摸事件
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
setBackgroundColor(Color.LTGRAY);
if (listener != null) {
// 獲取手指所在的Y座標點,並計算所觸摸的爲第幾個item的位置
int y = (int) event.getY();
int index = letters.size() * y / getHeight();
if (index >= 0 && index < letters.size()) {
listener.onTouchLetter(letters.get(index));
}
}
break;
default:
// 設置默認情況下的背景爲透明色
setBackgroundColor(Color.parseColor("#00ffffff"));
break;
}
return true;
}
/**
* 註冊監聽器
*
* @param listener
*/
public void setOnTouchLetterListener(OnTouchLetterListener listener) {
this.listener = listener;
}
/**
* 手指移動時會調用此監聽器的方法
*
* @author mm
*
*/
public interface OnTouchLetterListener {
void onTouchLetter(String letter);
}
}
在Activity中調用的方法:
lvSortKey.setOnTouchLetterListener(new OnTouchLetterListener() {
@Override
public void onTouchLetter(String letter) {
//獲取ListView中對應首字母相同的item
int pos=adapter.getPositionForSection(letter.charAt(0));
//定位到某個位置的Item
lvFriends.setSelection(pos);
}
});
顯示效果如下所示: