简单实现字母快速导航LetterView

现在在许多的应用都用到了索引的自定义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);
			}
		});
显示效果如下所示:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章