效果图
letter.png
选择和滑动的时候屏幕中间会显示选择的字母。
-
一 是测量这个控件的宽高,在onMeasure方法中
//获取控件宽度,通过画笔测量字母A来得到字母宽度,再加上左右的padding
widthSize=mPaint.measureText("A")+getPadingLeft+getPaddingRight;
//get 控件height,因为这个控件在layout文件里高度需要设置MatchParent,
所以直接从measuespec中获取高度
heightSize=MeasureSpec.getHightSize(heghtMeasureSpec); -
二 onDraw
//需要绘制26个字母,所以这里写个for循环
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的坐标
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();//获取现在手指在屏幕的Y坐标。
currentLetterPosition=(y+itemHeight/2)/itemHeight;//获得字母的坐标
//回调接口传到actvity
onletterTouchListener.onLetterTouch(letterArray[currentLetterPosition])
break; -
四回调方法
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
网友评论