效果图:android
须要两张图片,一张图片为背景,一张图片为滑动的点canvas
布局去指定一个自定义View对象:app
view.custom.shangguigucustomview.MyCustomSwitch
<?xml version="1.0" encoding="utf-8"?> <!-- 自定义开关 --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ShangGuiguTestActivity"> <view.custom.shangguigucustomview.MyCustomSwitch android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"/> </RelativeLayout>
自定义开关代码处理:ide
public class MyCustomSwitch extends View implements View.OnClickListener { private static final String TAG = "MyCustomSwitch"; /** * 定义两张图片 */ private Bitmap backroundBitmap; private Bitmap slideBitmap; /** * 定义画笔🖌️ */ private Paint paint; /** * 定义移动到右边到最大值 */ private int reghtMax; /** * 动态变化 距离到左边到值 */ private int leftValue; /** * 在布局中使用本类必需要实现这个构造方法,不然直接奔溃 * @param context * @param attrs */ public MyCustomSwitch(Context context, @Nullable AttributeSet attrs) { super(context, attrs); // 引用资源的两张图片 backroundBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.switch_background); slideBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.slide_button); // 实例化画笔 paint = new Paint(); paint.setAntiAlias(true); // 去掉锯齿 // 移动到右边最大值 reghtMax = backroundBitmap.getWidth() - slideBitmap.getWidth(); // 设置点击事件 setOnClickListener(this); } /*** * 一个视图从建立到显示到主要方法 * * View: * 1)构造方法,实例化,并建立一个视图 * 2)测量方法,用来测量显示到(视图大小(宽高)最终在这里肯定) * 3)绘制方法,绘制控件到显示 * * ViewGroup: * 1)构造方法,实例化,并建立一个视图 * 2)测量方法,用来测量显示到(视图大小最终在这里肯定) * 3)onLayout方法,用来指定 孩子位置相关 * 4) */ /** * 测量控件的本自定义视图(控件的宽高) */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(backroundBitmap.getWidth(), backroundBitmap.getHeight()); } /** * 绘制,把两张图片绘制好显示 */ @Override protected void onDraw(Canvas canvas) { // super.onDraw(canvas); // 画背景(开/关) 距离左边0,距离顶部0 canvas.drawBitmap(backroundBitmap, 0, 0, paint); // 画 用来移动的图片 // canvas.drawBitmap(slideBitmap, 10, 0, paint); // canvas.drawBitmap(slideBitmap, backroundBitmap.getWidth() / 2, 0, paint); // canvas.drawBitmap(slideBitmap, reghtMax, 0, paint); // canvas.drawBitmap(slideBitmap, 0, 0 , paint); canvas.drawBitmap(slideBitmap, leftValue, 0, paint); } private boolean isClick = true; @Override public void onClick(View view) { if (isClick) { Log.i(TAG, "点击了》》》》》》》》》》》》》》》》"); if (leftValue == 0) { leftValue = reghtMax; } else { leftValue = 0; } // 此方法让绘制方法从新执行 invalidate(); } } // 当前 拖动图片 距离左边到值 private float startX; // 记录初始值 private float defaultX; @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: defaultX = startX = event.getX(); // 只要按下就认为是点击事件,因此设置为true isClick = true; break; case MotionEvent.ACTION_UP: if (reghtMax /2 < leftValue){ leftValue = reghtMax; } else { leftValue = 0; } invalidate(); startX = event.getX(); break; case MotionEvent.ACTION_MOVE: float endX = event.getX(); float result = endX - startX; leftValue += result; // 判断越界 if (leftValue < 0) { leftValue = 0; } else if (leftValue > reghtMax) { leftValue = reghtMax; } // 此方法让绘制方法从新执行 invalidate(); // 值还原 startX = event.getX(); // 计算移动的差值,来决定,是不是移动 if (Math.abs(endX - defaultX) > 5) { isClick = false; } break; default: break; } return true; // 先本身来消耗 } }