安卓自定义switch,不再使用安卓自带switch。

安卓自带的switch可自定义性太差。而且在不同手机上显示效果可能不同。我就遇到再4.4上是长方形方块,在5.0上是圆弧形。

而且经测试switch再华为手机无法监听点击事件,应该是华为手机bug。未深入研究,深受安卓自带switch苦的我自定义View绘制了一个switch.

下面放效果图

点击带有滚动效果。需要的同学可以拿去。

下面放上源码。转载请注明出处:

 
 
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
import com.airainbow.secret_expert.R;
import com.airainbow.secret_expert.timer.BaseTimer;

/**
 * 编写 :易魏。
 * 日期:20180414
 * 功能 自定义switch
 * Created by Administrator on 2018/4/14.
 */
public class MySwitch extends View {
    private int checkColor;//背景选中颜色
    private int noCheckColor;//背景未选中颜色
    private int circleColor;//圆选中的颜色
    private boolean isCheck;//是否勾选
    private float outLineWidth;//外围描边宽度
    private int outLineColor;//外围描边颜色
    private int circleColorFalse;//圆未选中颜色
    private int checkColorDefault = 0xffff4081;//粉色 ARGB
    private int circleColorDefault = 0xffffffff;//白色
    private int circleColorFalseDefault=0xffff4081;
    private int noCheckColorDefault = 0xffffffff;//白色
    private float outLineWidthDefault = 2;
    private int outLineColorDefault = 0x74747400;
    private boolean isCheckDefault = false;
    private Path outPath = new Path();
    private Paint outPaint = new Paint();
    private Path inPath = new Path();
    private Paint inPaint = new Paint();
    private Paint circlePaint = new Paint();
    private int circleCenter = 0;
    private int width, height;
    private ChangeSwitchStatus changeSwitchStatus = new ChangeSwitchStatus();
    private SwitchOnClickListener switchOnClickListener;

    public MySwitch(Context context) {
        super(context);
    }

    public MySwitch(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MySwitch);
        checkColor = typedArray.getColor(R.styleable.MySwitch_checkColor, checkColorDefault);
        isCheck = typedArray.getBoolean(R.styleable.MySwitch_isCheck, isCheckDefault);
        noCheckColor = typedArray.getColor(R.styleable.MySwitch_noCheckColor, noCheckColorDefault);
        circleColor = typedArray.getColor(R.styleable.MySwitch_circleColor, circleColorDefault);
        outLineWidth = typedArray.getDimension(R.styleable.MySwitch_outLineWidth, outLineWidthDefault);
        outLineColor = typedArray.getColor(R.styleable.MySwitch_outLineColor, outLineColorDefault);
        circleColorFalse=typedArray.getColor(R.styleable.MySwitch_circleColorFalse,circleColorFalseDefault);
        circlePaint.setAntiAlias(true);
        circlePaint.setStyle(Paint.Style.FILL);
        circlePaint.setColor(circleColor);
        inPaint.setAntiAlias(true);
        inPaint.setStyle(Paint.Style.FILL);
        outPaint.setAntiAlias(true);
        outPaint.setStyle(Paint.Style.FILL);
        outPaint.setStrokeWidth(outLineWidth);
        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!changeSwitchStatus.isRun) {
                    changeSwitchStatus.start();
                }

            }
        });
    }

    public MySwitch(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        width = canvas.getWidth();
        height = canvas.getHeight();
        inPath.reset();
        outPath.reset();
        inPath.addArc(outLineWidth, outLineWidth, height - outLineWidth, height - outLineWidth, 0, 360);
        inPath.addArc(width - height + outLineWidth, outLineWidth, width - outLineWidth, height - outLineWidth, 0, 360);
        inPath.addRect((height / 2) + outLineWidth, outLineWidth, width - (height / 2) - outLineWidth, height - outLineWidth, Path.Direction.CW);
        outPath.addArc(0, 0, height, height, 90, 270);
        outPath.addArc(width - height, 0, width, height, 180, 360);
        outPath.addRect(height / 2, 0, width - (height / 2), height, Path.Direction.CW);
        if (isCheck) {
            inPaint.setColor(checkColor);
            circlePaint.setColor(circleColor);
            if (circleCenter == 0) {
                circleCenter = (int) (width - outLineWidth - height / 2);
            }
        } else {
            circlePaint.setColor(circleColorFalse);
            inPaint.setColor(noCheckColor);
            if (circleCenter == 0) {
                circleCenter = (int) (outLineWidth + height / 2);
            }
        }
        outPaint.setColor(outLineColor);
        canvas.drawPath(outPath, outPaint);
        canvas.drawPath(inPath, inPaint);
        canvas.drawCircle(circleCenter, height / 2, height / 3, circlePaint);
    }

    public SwitchOnClickListener getSwithOnClickListener() {
        return switchOnClickListener;
    }

    public void setSwithOnClickListener(SwitchOnClickListener swithOnClickListener) {
        this.switchOnClickListener = swithOnClickListener;
    }
    public boolean isCheck() {
        return isCheck;
    }

    public void setCheck(boolean check) {
        isCheck = check;
    }
    public interface SwitchOnClickListener {
        void onClick(boolean check);
    }

    public int getCheckColor() {
        return checkColor;
    }

    public void setCheckColor(int checkColor) {
        this.checkColor = checkColor;
    }

    public int getCircleColor() {
        return circleColor;
    }

    public void setCircleColor(int circleColor) {
        this.circleColor = circleColor;
    }

    public int getCircleColorFalse() {
        return circleColorFalse;
    }

    public void setCircleColorFalse(int circleColorFalse) {
        this.circleColorFalse = circleColorFalse;
    }

    public int getNoCheckColor() {
        return noCheckColor;
    }

    public void setNoCheckColor(int noCheckColor) {
        this.noCheckColor = noCheckColor;
    }

    public int getOutLineColor() {
        return outLineColor;
    }

    public void setOutLineColor(int outLineColor) {
        this.outLineColor = outLineColor;
    }

    public float getOutLineWidth() {
        return outLineWidth;
    }

    public void setOutLineWidth(float outLineWidth) {
        this.outLineWidth = outLineWidth;
    }

    class ChangeSwitchStatus extends BaseTimer {
        private int oneMove;
        private boolean isRun = false;

        @Override
        public void start() {
            oneMove = (((int) (width - outLineWidth - height / 2)) - ((int) (outLineWidth + height / 2))) / 30;
            handler.post(this);
            isRun=true;
        }

        @Override
        public void stop() {
            handler.removeCallbacks(this);
            if (switchOnClickListener!=null){
                switchOnClickListener.onClick(isCheck);
            }
            isRun=false;
        }

        @Override
        public void destroy() {
            handler.removeCallbacks(this);
            handler = null;
        }

        @Override
        public void run() {
            handler.removeCallbacks(this);
//            handler.postDelayed(this, 1);
            //重新绘制需要时间约等于刷新率
            handler.post(this);
            if (isCheck) {
                if (circleCenter > (int) (outLineWidth + height / 2)) {
                    circleCenter -= oneMove;
                } else {
                    isCheck = false;
                    stop();
                }
            } else {
                if (circleCenter < (width - outLineWidth - height / 2)) {
                    circleCenter += oneMove;
                } else {
                    isCheck = true;
                    stop();
                }
            }
            invalidate();
        }

    }

}

下面是BaseTimer源码。定义了几个抽象方法。

import android.os.Handler;

/**
 * Created by Administrator on 2018/4/14.
 */
/**
 * 编写 :易魏。
 * 日期:20180414
 * 功能 Timer
 * Created by Administrator on 2018/4/14.
 */
public abstract class BaseTimer implements Runnable {
    public Handler handler=new Handler();
    public abstract void start();
    public abstract void stop();
    public abstract void destroy();
    @Override
    public void run() {

    }
}

最后是attrs,自定义属性

<declare-styleable name="MySwitch">
    <attr name="isCheck" format="boolean"></attr>
    <attr name="checkColor" format="color|reference"></attr>
    <attr name="noCheckColor" format="color|reference"></attr>
    <attr name="circleColor" format="color|reference"></attr>
    <attr name="outLineWidth" format="dimension|reference"></attr>
    <attr name="outLineColor" format="color|reference"></attr>
    <attr name="circleColorFalse" format="color|reference"></attr>
</declare-styleable>

使用方法。在要使用的地方引用这个MySwitch

可自定义属性如上图,在根布局添加这句话

xmlns:app="http://schemas.android.com/apk/res-auto"

默认自动导入。

属性含义

   private int checkColor;//背景选中颜色
    private int noCheckColor;//背景未选中颜色
    private int circleColor;//圆选中的颜色
    private boolean isCheck;//是否勾选
    private float outLineWidth;//外围描边宽度
    private int outLineColor;//外围描边颜色
    private int circleColorFalse;//圆未选中颜色

设置switch变化监听

setSwithOnClickListener

获取当前状态

isCheck

然后你就可以愉快的玩耍了。

猜你喜欢

转载自blog.csdn.net/qq_34721782/article/details/79939083