专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Android 自定义ToggleButton

效果预览

71_1.png

代码实现

public class ToggleButton extends View {

    private int mLineWidth = 5;
    private int mTextSize = 18;
    private TextPaint mTextPaint = null;
    private int mTouchSlop = 0;
    private boolean isTouchMove = false;
    private int offsetX = 0;
    private int contentWidth = 0;
    private int contentHeight = 0;
    private int slideBarRadius;
    float startX = 0f;
    float startY = 0f;
    private int STATUS_LEFT = 0;
    private int STATUS_RIGHT = 1;

    private int mState = STATUS_LEFT;

    private ValueAnimator mSlideAnimator = null;

    public ToggleButton(Context context) {
        this(context, null);
    }

    public ToggleButton(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ToggleButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //设置此项true,否则无法滑动
        mTextPaint = initPaint();
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop() / 2;

        setClickable(true);
        setFocusable(true);
        setFocusableInTouchMode(true);

        setBackgroundColor(0xffffffff);

    }

    private TextPaint initPaint() {
        // 实例化画笔并打开抗锯齿
        TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(dpTopx(mLineWidth));
        paint.setTextSize(dpTopx(mTextSize));
        return paint;
    }

    private float dpTopx(int dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (heightMode == MeasureSpec.UNSPECIFIED) {
            heightSize = getPaddingTop() + getPaddingBottom() + 100;
        } else if (heightMode == MeasureSpec.AT_MOST) {
            int disire = getPaddingTop() + getPaddingBottom() + 100;
            heightSize = Math.min(disire, heightSize);
        }

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        if (widthMode == MeasureSpec.UNSPECIFIED) {
            widthSize = getPaddingTop() + getPaddingBottom() + 280;
        } else if (widthMode == MeasureSpec.AT_MOST) {
            int disire = getPaddingTop() + getPaddingBottom() + 280;
            widthSize = Math.min(disire, widthSize);
        }

        setMeasuredDimension(widthSize, heightSize);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int w = getWidth();
        int h = getHeight();

        int lineWidthPixel = (int) mTextPaint.getStrokeWidth();

        contentWidth = w - 2 * lineWidthPixel;
        contentHeight = h - 2 * lineWidthPixel;

        int radius = Math.min(w, h) / 2 - lineWidthPixel / 2;
        if (radius < 0) return;

        mTextPaint.setColor(Color.DKGRAY);
        mTextPaint.setStyle(Paint.Style.STROKE);
        RectF outlineRectF = new RectF(
                lineWidthPixel / 2,
                lineWidthPixel / 2,
                lineWidthPixel + contentWidth + lineWidthPixel / 2,
                lineWidthPixel + contentHeight + lineWidthPixel / 2
        );
        canvas.drawRoundRect(outlineRectF, radius, radius, mTextPaint);

        RectF innerRectF = new RectF(
                lineWidthPixel,
                lineWidthPixel,
                lineWidthPixel + contentWidth,
                lineWidthPixel + contentHeight
        );
        mTextPaint.setColor(0xffffffff);
        mTextPaint.setStyle(Paint.Style.FILL);
        canvas.drawRoundRect(innerRectF, radius, radius, mTextPaint);

        mTextPaint.setColor(Color.DKGRAY);
        RectF middleRect = new RectF(
                w / 2 - lineWidthPixel / 2,
                lineWidthPixel * 3,
                w / 2 + lineWidthPixel / 2,
                h - lineWidthPixel * 3
        );
        mTextPaint.setStyle(Paint.Style.FILL);
        canvas.drawRoundRect(middleRect, radius, radius, mTextPaint);

        slideBarRadius = contentHeight / 2;

        RectF circleRectF = new RectF(
                lineWidthPixel + lineWidthPixel + offsetX,
                0,
                slideBarRadius * 2 + offsetX,
                h
        );

        mTextPaint.setColor(Color.GRAY);
        canvas.drawCircle(circleRectF.centerX(), circleRectF.centerY(), slideBarRadius, mTextPaint);

        if(mState==STATUS_LEFT) {
            mTextPaint.setColor(Color.CYAN);
        }else{
            mTextPaint.setColor(Color.RED);
        }
        canvas.drawCircle(circleRectF.centerX(), circleRectF.centerY(), slideBarRadius / 4, mTextPaint);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = event.getAction();
        int lineWidthPixies = (int) dpTopx(mLineWidth);

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX();
                startY = event.getY();
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
            case MotionEvent.ACTION_MOVE:

                float currentX = event.getX();
                float currentY = event.getY();

                float dy = Math.abs(currentY - startY);
                float dx = Math.abs(currentX - startX);

                if (dy <= dx && dx >= mTouchSlop) {
                    isTouchMove = true;
                }

                if (isTouchMove) {
                    offsetX = (int) (currentX - slideBarRadius);
                    startX = currentX;
                    startY = currentY;

                    if (offsetX < (lineWidthPixies)) {
                        offsetX = 0; //最左边
                    } else if (offsetX > contentWidth - slideBarRadius * 2) { //最右边
                        offsetX = contentWidth - slideBarRadius * 2;
                    }

                    postInvalidateOnAnimation();
                }

                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_OUTSIDE:

                getParent().requestDisallowInterceptTouchEvent(false);
                startX = event.getX();
                if (startX <= getWidth() / 2) {
                    if(isTouchMove){
                        offsetX = 0;
                        mState = STATUS_LEFT;
                    }else{
                        startSlideBarAnimation(offsetX,0,STATUS_LEFT);
                    }
                } else {
                    if(isTouchMove){
                        mState = STATUS_RIGHT;
                        offsetX = contentWidth - 2 * slideBarRadius;
                    }else{
                        startSlideBarAnimation(offsetX,contentWidth - 2 * slideBarRadius,STATUS_RIGHT);
                    }
                }
                isTouchMove = false;
                postInvalidateOnAnimation();
                break;
        }

        return super.onTouchEvent(event);
    }

    public void postInvalidateOnAnimation() {
        if (Build.VERSION.SDK_INT >= 16) {
            super.postInvalidateOnAnimation();
        } else {
            postInvalidate();
        }
    }

    public void setState(int state) {
        this.mState = state;
        if (state == STATUS_LEFT) {
            offsetX = 0;
        } else {
            offsetX = contentWidth - 2 * slideBarRadius;
        }
        postInvalidate();
    }

    public void startSlideBarAnimation(int from, int to, final int state) {
        if (mSlideAnimator != null) {
            mSlideAnimator.cancel();
        }
        mSlideAnimator = ValueAnimator.ofInt(from, to).setDuration(300);
        mSlideAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        mSlideAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                offsetX = (int) animation.getAnimatedValue();
                float fraction = animation.getAnimatedFraction();
                if(fraction>=0.9){
                    mState = state;
                }
                postInvalidate();
            }
        });
        mSlideAnimator.start();
    }
}

未经允许不得转载:搜云库技术团队 » Android 自定义ToggleButton

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们