效果圖: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; // 先本身來消耗 } }