android SwitchButton 纯代码实现,仿5.0原生

个人觉得5.0以后原生的switch样式不错,但是5.0以下的版本却不能用,再加上本身这个控件有bug(滑到中间就停起了,看图2。。。fuck),以前也用过第三方的switchbutton但是个人觉得很麻烦,要添加图片,还要增加自定义属性等。于是小弟决定自己写一个,本着“懒不惊人死不休”的精神用纯代码来实现。只需要这一个SwitchButton.java文件即可,方便快捷。当然也可以增加自定义属性。
可以通过setXXX的方法来更改一些属性。

水平有限,不喜勿喷

直接上图:上面的是自定义,下面是官方的
如图
FUCK
代码如下:

package com.sly.view;

import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.ImageButton;

/**
 * 自定义SwitchButton(仿Android 5.0自带)
 * 
 * @author HeyGays
 *
 */
public class SwitchButton extends ImageButton {

    private final int ROUND_MARGIN = 2;// 圆点按钮的外边距dp,避免圆点边缘被遮盖

    private Paint paint;// 画圆点的笔
    private boolean isOn;// 开关状态,左关右开
    private float touchX = 0;// 手指按下的x坐标
    private int touchSlop;// 最小滑动距离
    private int backHeight = 24;// 背景默认高度dp
    private int backWidth;// 背景宽度dp
    private int backPadding = 5;// 背景的默认padding dp
    private int backColor_Off = Color.GRAY;// 背景的默认填充颜色
    private int backColor_On = Color.DKGRAY;// 背景的默认填充颜色
    private int backRoundRadius = backHeight;// 背景的默认圆角半径dp
    private int m = 0;// 相对于最左的位移距离 dp
    private int m_Max;// m的最大坐标
    private int round_Size;// 圆点的大小
    private GradientDrawable gd;// 背景drawble
    private RectF roundBtnRect = new RectF();// 圆点所在矩形范围

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

    public SwitchButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SwitchButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initSize();
        initBack();
        initPaint();
    }

    /**
     * 初始化一些尺寸
     */
    private void initSize() {
        touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        // 根据高度计算圆点大小
        round_Size = backHeight - 2 * ROUND_MARGIN;
        // 根据圆点大小计算开关宽度
        backWidth = 2 * (round_Size + ROUND_MARGIN);
        // 根据宽度计算最大位移坐标
        m_Max = backWidth - ROUND_MARGIN - round_Size - 1;
    }

    /**
     * 初始化背景
     */
    private void initBack() {
        int padding = dp2px(backPadding);
        gd = new GradientDrawable();
        gd.setColor(backColor_Off);
        gd.setCornerRadius(dp2px(backRoundRadius));
        if (padding == 0) {// 防止黑边
            gd.setStroke(padding, Color.TRANSPARENT);
        }
        setPadding(padding, padding, padding, padding);
        setImageDrawable(gd);
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {
        setLayerType(LAYER_TYPE_SOFTWARE, null);// 关闭硬件加速
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.LTGRAY);
        paint.setStyle(Style.FILL_AND_STROKE);
        paint.setShadowLayer(2, 0, 2, Color.DKGRAY);
        paint.setStrokeWidth(1);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(dp2px(backWidth), dp2px(backHeight));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        roundBtnRect.left = dp2px(ROUND_MARGIN + m);
        roundBtnRect.top = dp2px(ROUND_MARGIN);
        roundBtnRect.right = roundBtnRect.left + dp2px(round_Size);
        roundBtnRect.bottom = roundBtnRect.top + dp2px(round_Size);
        canvas.drawArc(roundBtnRect, 0, 360, false, paint);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touchX = event.getX();
            break;
        case MotionEvent.ACTION_MOVE:
            getParent().requestDisallowInterceptTouchEvent(true);
            if (Math.abs(event.getX() - touchX) > touchSlop) {
                int moveX = (int) (event.getX() - touchX);
                if (isOn) {
                    if (moveX <= 0) {
                        m = m_Max + (moveX / 3) < 0 ? 0 : m_Max + (moveX / 3);// 按钮的滑动速度等于手指的1/3
                    } else {
                        m = m_Max;
                    }
                } else {
                    if (moveX >= 0) {
                        m = (moveX / 3) >= m_Max ? m_Max : moveX / 3;
                    } else {
                        m = 0;
                    }
                }
                invalidate();
            }
            break;
        case MotionEvent.ACTION_UP:
            if (Math.abs(event.getX() - touchX) > touchSlop) {
                if (m > m_Max / 2) {
                    isOn = false;
                } else {
                    isOn = true;
                }
            }
            move();
            break;
        }
        return true;
    }

    /**
     * 移动动画
     */
    private void move() {
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {

                post(new Runnable() {
                    @Override
                    public void run() {
                        if (!isOn) {
                            m++;
                        } else {
                            m--;
                        }
                        if (m >= m_Max) {
                            m = m_Max;
                            isOn = true;
                            gd.setColor(backColor_On);
                            setImageDrawable(gd);
                            removeCallbacks(this);
                            cancel();
                        } else if (m <= 0) {
                            m = 0;
                            isOn = false;
                            gd.setColor(backColor_Off);
                            setImageDrawable(gd);
                            removeCallbacks(this);
                            cancel();
                        }
                        invalidate();
                    }
                });

            }
        }, 0, 10);
    }

    /**
     * dip转为 px
     */
    public int dp2px(int dipValue) {
        float scale = getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    /**
     * 设置圆点的颜色
     * 
     * @param roundBtnColor
     */
    public void setRoundBtnColor(int roundBtnColor) {
        paint.setColor(roundBtnColor);
        invalidate();
    }

    /**
     * 设置背景高度
     * 
     * @param backHeight
     */
    public void setBackHeight(int backHeight) {
        this.backHeight = backHeight < this.backHeight ? this.backHeight : backHeight;
        initSize();
    }

    /**
     * 设置背景padding
     * 
     * @param backPadding
     */
    public void setBackPadding(int backPadding) {
        if (backPadding <= 0) {
            backPadding = 0;
        }
        if (backPadding > backHeight) {
            backPadding = this.backPadding;
        }
        this.backPadding = backPadding;
        initBack();
    }

    /**
     * 设置关闭的背景颜色
     * 
     * @param backColor_On
     */
    public void setBackColorWithOff(int backColor_Off) {
        this.backColor_Off = backColor_Off;
        initBack();
    }

    /**
     * 设置打开的背景颜色
     * 
     * @param backColor_On
     */
    public void setBackColorWithOn(int backColor_On) {
        this.backColor_On = backColor_On;
        initBack();
    }

    /**
     * 返回开关状态
     * 
     * @return
     */
    public boolean isOn() {
        return isOn;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值