美文网首页
android 自定义26个字母控件

android 自定义26个字母控件

作者: 3abc0fc15fc2 | 来源:发表于2021-04-17 09:31 被阅读0次

效果图


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;
    }
    }
    ...

相关文章

网友评论

      本文标题:android 自定义26个字母控件

      本文链接:https://www.haomeiwen.com/subject/jmkulltx.html