美文网首页
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