效果圖
選擇和滑動的時候屏幕中間會顯示選擇的字母耿芹。
一 是測量這個控件的寬高崭篡,在onMeasure方法中
//獲取控件寬度,通過畫筆測量字母A來得到字母寬度吧秕,再加上左右的padding
widthSize=mPaint.measureText("A")+getPadingLeft+getPaddingRight;
//get 控件height,因為這個控件在layout文件里高度需要設(shè)置MatchParent琉闪,
所以直接從measuespec中獲取高度
heightSize=MeasureSpec.getHightSize(heghtMeasureSpec);二 onDraw
//需要繪制26個字母,所以這里寫個for循環(huán)
itemHight=(getHight-getPaddingTop)/26;//each letter height
//繪制字母的基線位置
baselineY=itemHeight/2+(metrcis.bottom-metrics.top)/2-metrics.bottom;
for(int i=0;i<letterArray.length;i++){
x=getWidth/2-mPaint.measureText(letterArray[i])/2;//x的坐標(biāo)
y=itemHight*i+baselineY;
if(i==currentLetterpostion)
canvas.drawText(letterArray[i],x,y,mSelectPaint);//繪制選中文字
else
canvas.drawText(letterArray[i],x,y,mNormalPaint);//繪制normal 文字
}三 onTouch Event
case DOWN:
case MOVE:
int y=getY();//獲取現(xiàn)在手指在屏幕的Y坐標(biāo)砸彬。
currentLetterPosition=(y+itemHeight/2)/itemHeight;//獲得字母的坐標(biāo)
//回調(diào)接口傳到actvity
onletterTouchListener.onLetterTouch(letterArray[currentLetterPosition])
break;四回調(diào)方法
private OnletterTouchListener onletterTouchListener;
Inerface OnLetterTouchListener{
onLetterTouch(CharSequence letter)
}
public void setOnLetterTouchListener(OnletterTouchListener Listener){
this. onletterTouchListener=listener;
}-
以上是大致的流程和思路塘偎,以下是源碼
...
public class LetterBar extends View {
/**- normal letter paint,focus paint
/
private Paint mPaint,focusPaint;
/* - each letter height
/
private float itemHeight;
/* - current y position,default is 0f
*/
private int mCurrentY=0;
private final String[] lettersArray = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
"L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"};
public LetterBar(Context context) {
this(context,null);
}public LetterBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}public LetterBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint=new Paint();
mPaint.setDither(true);
mPaint.setAntiAlias(true);
mPaint.setTextSize(sp2px(20));
focusPaint=new Paint();
focusPaint.setDither(true);
focusPaint.setAntiAlias(true);
focusPaint.setTextSize(sp2px(20));
focusPaint.setColor(Color.RED);
}private float sp2px(int sp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,sp,getResources().getDisplayMetrics());
}@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);float textWidth=mPaint.measureText("W"); int widthSize= (int) (textWidth+getPaddingLeft()+getPaddingRight()); int heightSize=MeasureSpec.getSize(heightMeasureSpec)-getPaddingTop()-getPaddingBottom(); setMeasuredDimension(widthSize,heightSize);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);itemHeight=(getHeight()-getPaddingBottom()-getPaddingTop())/lettersArray.length; Paint.FontMetrics metrics = mPaint.getFontMetrics(); float dy=(metrics.descent-metrics.ascent)/2-metrics.descent; float basey=itemHeight/2+dy; int itemWidth=0; int itemLetterY=0; for(int i=0;i<lettersArray.length-1;i++){ itemWidth= (int) (mPaint.measureText(lettersArray[i])); itemLetterY= (int) (itemHeight*i+itemHeight/2+basey); if(mCurrentY==i) { Log.d("TAG","itemLetterY="+itemLetterY+" i="+i); canvas.drawText(lettersArray[i], getWidth() / 2 - itemWidth / 2, +itemLetterY, focusPaint); } else canvas.drawText(lettersArray[i],getWidth()/2-itemWidth/2,+itemLetterY,mPaint); }
}
@Override
public boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){ case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: float letterY=(event.getY()-getPaddingTop()-itemHeight/2)/itemHeight; if(letterY==mCurrentY) return true; mCurrentY= (int) letterY; if(mCurrentY<0) mCurrentY=0; if(mCurrentY>lettersArray.length-1) mCurrentY=lettersArray.length-1; onLetterTouchListener.onLetterTouch(lettersArray[mCurrentY],true); invalidate(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if(mCurrentY<0) mCurrentY=0; if(mCurrentY>lettersArray.length-1) mCurrentY=lettersArray.length-1; synchronized (this) { postDelayed(new Runnable() { @Override public void run() { onLetterTouchListener.onLetterTouch(lettersArray[mCurrentY], false); } }, 1000); invalidate(); } break; } Log.d("TAG","mCurrentY="+mCurrentY); return true;
}
private OnLetterTouchListener onLetterTouchListener;
public interface OnLetterTouchListener{
void onLetterTouch(CharSequence letter,boolean isTouch);
}
public void setOnLetterTouchListener(OnLetterTouchListener listener){
this.onLetterTouchListener=listener;
}
}
... - normal letter paint,focus paint