Android 怎么自定义绘制一个切换按钮(二)

115 阅读2分钟

这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战 昨天简单的介绍了绘制开关的准备工作,以及一些初始化的工作,接下来,开始我们的绘制过程,怎么样把我们准备的好的画笔,形状绘制到画布上,然后形成我们想要的东西。也就是我们的onDraw();

@Override
    protected void onDraw(Canvas canvas) {
      
            int radius;//圆角
            radius = backRect.height() / 2;
            //画关闭
            if (enable) {
                //画关闭背景外框
                closePaint.setColor(linearColor);
                closePaint.setStyle(Paint.Style.STROKE);
                closePaint.setStrokeWidth(strokeWidth);
                canvas.drawRoundRect(lineCircleRect, radius, radius, closePaint);

                //画关闭背景
                closePaint.setColor(closeColor);
                closePaint.setStyle(Paint.Style.FILL);
                canvas.drawRoundRect(closeRect, radius, radius, closePaint);
            } else {
                //画关闭背景外框
                closePaint.setColor(linearColor);
                closePaint.setStyle(Paint.Style.STROKE);
                closePaint.setStrokeWidth(strokeWidth);
                canvas.drawRoundRect(lineCircleRect, radius, radius, closePaint);

                //画关闭背景
                closePaint.setColor(closeColor);
                closePaint.setStyle(Paint.Style.FILL);
                canvas.drawRoundRect(closeRect, radius, radius, closePaint);

                //阴影
                closePaint.setColor(Color.WHITE);
                closePaint.setStyle(Paint.Style.FILL);
                backCircleRect.set(backRect);
                closePaint.setAlpha(disableAlpha);
                canvas.drawRoundRect(backCircleRect, radius, radius, closePaint);
            }

            //画开启
            openPaint.setColor(openColor);
            openPaint.setAlpha(enableAlpha);
            backCircleRect.set(backRect);
            canvas.drawRoundRect(backCircleRect, radius, radius, openPaint);
            //画不可用
            openPaint.setColor(Color.WHITE);
            openPaint.setAlpha(disableAlpha);
            canvas.drawRoundRect(backCircleRect, radius, radius, openPaint);
            //画小圆
            frontRect.set(frontRectLeft, rimSize, frontRectLeft + backRect.height() - 2 * rimSize, backRect.height() - rimSize);
            frontCircleRect.set(frontRect);
            paintCircle.setColor(Color.WHITE);
            paintCircle.setShadowLayer(strokeRound, 0, 0, linearColor);
            canvas.drawRoundRect(frontCircleRect, radius, radius, paintCircle);
            setLayerType(LAYER_TYPE_SOFTWARE, null);
        }
    }

接下来我们来绘制我们触摸事件,开和关的处理,点击事件,滑动事件

private boolean isActionMove = false;
private boolean slideable = false;//是否可以滑动

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!enable)
            return super.onTouchEvent(event);
        int action = MotionEventCompat.getActionMasked(event);
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                eventStartX = (int) event.getRawX();
                break;
            case MotionEvent.ACTION_MOVE:
                if (slideable) {
                    eventLastX = (int) event.getRawX();
                    diffX = eventLastX - eventStartX;
                    int tempX = diffX + frontRectLeftBegin;
                    tempX = (tempX > maxLeft ? maxLeft : tempX);
                    tempX = (tempX < minLeft ? minLeft : tempX);
                    if (tempX >= minLeft && tempX <= maxLeft) {
                        frontRectLeft = tempX;
                        enableAlpha = (int) (255 * (float) tempX / (float) maxLeft);
                        isActionMove = true;
                        invalidateView();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                sliderMove(event);
                break;
            case MotionEvent.ACTION_CANCEL:
                if (isActionMove) {
                    sliderMove(event);
                }
                Log.e("onTouchEvent:", "ACTION_CANCEL");
                break;
            default:
                break;
        }
        return true;
    }
    

滑动处理

  /***
  * 执行滑动
  * @param event
  */
 private void sliderMove(MotionEvent event) {
     int wholeX = (int) (event.getRawX() - eventStartX);
     frontRectLeftBegin = frontRectLeft;
     boolean toRight;
     toRight = (frontRectLeftBegin > maxLeft / 2 ? true : false);
     if (Math.abs(wholeX) < 3) {
         toRight = !toRight;
     }
     moveToDest(toRight);
 }

执行完一个绘制动作,需要刷新整个绘制的画布,重新绘制



    /**
     * 重新绘制
     */
    private void invalidateView() {
        if (Looper.getMainLooper() == Looper.myLooper()) {
            invalidate();
        } else {
            postInvalidate();
        }
    }

执行切换操作动画,完成开和关的动画,透明度变化,切换监听回调

   /***
    * 切换操作
    * @param toRight
    */
   public void moveToDest(final boolean toRight) {
       /****切换动画****/
       ValueAnimator toDestAnim = ValueAnimator.ofInt(frontRectLeft, toRight ? maxLeft : minLeft);
       toDestAnim.setDuration(300);
       toDestAnim.setInterpolator(new AccelerateDecelerateInterpolator());
       toDestAnim.start();
       toDestAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

           @Override
           public void onAnimationUpdate(ValueAnimator animation) {
               setLayerType(LAYER_TYPE_NONE, null);
               frontRectLeft = (Integer) animation.getAnimatedValue();
               enableAlpha = (int) (255 * (float) frontRectLeft / (float) maxLeft);
               invalidateView();
           }
       });
       toDestAnim.addListener(new AnimatorListenerAdapter() {
           @Override
           public void onAnimationEnd(Animator animation) {
               if (toRight) {
                   isOpen = true;
                   frontRectLeftBegin = maxLeft;
                   enableAlpha = 255;
               } else {
                   isOpen = false;
                   frontRectLeftBegin = minLeft;
                   enableAlpha = 0;
               }

               if (phSwitchButtonListener != null)
                   phSwitchButtonListener.onStatusChanged(PHSwitchButton.this, isOpen);
           }
       });
   }

   /***
    * 设置监听
    * @param listener
    */
   public void setPHSwitchButtonListener(PHSwitchButtonListener listener) {
       this.phSwitchButtonListener = listener;
   }

一步一步来,写到哪里想到哪里,少什么补什么,对外公开滑动的监听,交给外部处理业务逻辑

总结

以上就是自定义的一个开关按钮的大部分内容,涉及到的东西也不是很多,分析清楚,就可以把大体的内容绘制出来。