簡單實現字母快速導航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);
			}
		});
顯示效果如下所示:

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