安卓自带的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
然后你就可以愉快的玩耍了。