Android-自定義開關

效果圖: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; // 先本身來消耗
    }
}
相關文章
相關標籤/搜索