Android-自定義開關(ViewGroup版)

雖然實現自定義開關,一般狀況下都是繼承View,比較合理方便快捷一些android

可是我今天想去繼承ViewGroup來實現自定義開關來玩玩canvas

 

效果圖:ide

 

 

佈局代碼:佈局

<!-- 自定義開關ViewGroup版 -->
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myswitch="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=".upgrade.MainActivity">

    <custom.view.upgrade.my_switch_viewgroup.MySwitch2
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:background="#33F00000">

    </custom.view.upgrade.my_switch_viewgroup.MySwitch2>

</RelativeLayout>

效果:this

 

佈局代碼:spa

<!-- 自定義開關ViewGroup版 -->
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myswitch="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=".upgrade.MainActivity">

    <custom.view.upgrade.my_switch_viewgroup.MySwitch2
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:background="#33F00000">

        <!-- 第一個子控件 -->
        <ImageView
            android:id="@+id/iv_switch_bg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/switch_background"/>

        <!-- 第二個子控件 -->
        <ImageView
            android:id="@+id/iv_switch_drag"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/switch_drag"/>

    </custom.view.upgrade.my_switch_viewgroup.MySwitch2>

</RelativeLayout>

 

自定義開關繼承ViewGroup代碼:code

 

package custom.view.upgrade.my_switch_viewgroup;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

public class MySwitch2 extends ViewGroup implements View.OnClickListener , View.OnTouchListener {

    private static final String TAG = MySwitch2.class.getSimpleName();

    private View switchBackground;
    private View switchGrag;

    private int switchBackgroundWidth;
    private int switchBackgroundHeight;
    private int switchGragWidth;
    private int switchGragHeight;

    private boolean onCreate = false;

    // 開關的狀態
    private boolean switchStatus;

    public MySwitch2(Context context, AttributeSet attrs) {
        super(context, attrs);

        // 若是是這樣寫的話,是給整個粉紅色正方形區域都設置了點擊事件
        // setOnClickListener(this);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        switchBackground = getChildAt(0);
        switchGrag = getChildAt(1);

        onCreate = true;

        // 給子控件設置點擊事件
        switchBackground.setOnClickListener(this);
        switchGrag.setOnClickListener(this);

        // 給子控件設置Touch事件
        switchBackground.setOnTouchListener(this);
        switchGrag.setOnTouchListener(this);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // 測量第一個子控件
        LayoutParams switchBgParams = switchBackground.getLayoutParams();
        switchBackground.measure(switchBgParams.width, switchBgParams.height);

        // 測量第二個子控件
        LayoutParams switchGragParams = switchGrag.getLayoutParams();
        switchGrag.measure(switchGragParams.width, switchGragParams.height);

        // -2 表明是wrap_content
        // Log.d(TAG, "測量方法>>> switchGragParams.width" + switchGragParams.width);

        // 獲得測量後的高和寬
        if (onCreate) {
            onCreate = false;
            switchBackgroundWidth = switchBackground.getMeasuredWidth();
            switchBackgroundHeight = switchBackground.getMeasuredHeight();
            switchGragWidth = switchGrag.getMeasuredWidth();
            switchGragHeight = switchGrag.getMeasuredHeight();
        }

        // 在拖動開關的時候,測量會執行不少次,由於在拖動的過程當中,開關Grag會的測量寬度會不斷變化
        // Log.d(TAG, "測量方法>>> switchBackgroundWidth:" + switchBackgroundWidth + " switchGragWidth:" + switchGragWidth);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 給子控件排版指定位置
        switchBackground.layout(
                getMeasuredWidth() / 2 - switchBackground.getWidth() / 2,
                getMeasuredHeight() / 2 - switchBackground.getHeight() / 2,
                switchBackground.getMeasuredWidth() + (getMeasuredWidth() / 2 - switchBackground.getWidth() / 2),
                switchBackground.getMeasuredHeight() + (getMeasuredHeight() / 2 - switchBackground.getHeight() / 2));

        /*switchGrag.layout(
                getMeasuredWidth() / 2 - (switchGrag.getWidth() / 2),
                getMeasuredHeight()  /2 - (switchGrag.getHeight() / 2),
                switchGrag.getMeasuredWidth() + getMeasuredWidth() / 2 - (switchGrag.getWidth() / 2),
                switchGrag.getMeasuredHeight() + getMeasuredHeight()  /2 - (switchGrag.getHeight() / 2));*/

        int gragL = getMeasuredWidth() / 2 - (switchBackground.getWidth() / 2);
        int gragT = getMeasuredHeight()  / 2 - (switchGrag.getHeight() / 2);
        switchGrag.layout(
                gragL,
                gragT,
                switchGrag.getMeasuredWidth() + gragL,
                switchGrag.getMeasuredHeight() + gragT);

        // 動的是兩個子控件
        // scrollTo(90, 0);
    }

    /**
     * 打開開關
     * @return
     */
    /*private int getOpenSwitch() {
        return getMeasuredWidth() / 2;
    }*/

    /**
     * 關閉開關
     * @return
     */
    /*private int getCloseSwitch() {
        return getMeasuredWidth() / 2 - (switchBackground.getWidth() / 2);
    }*/

    /**
     * 開關滑動的按鈕
     * @param move
     */
    private void setScrollMove(int move) {

        int countValue = (switchBackground.getMeasuredWidth() - switchGrag.getMeasuredWidth()) / 2;

        int countValue2 = (switchBackgroundWidth - switchGragWidth);

        // Log.d(TAG, "switchBackgroundWidth:" + switchBackgroundWidth + " switchGragWidth:" + switchGragWidth);

        Log.d(TAG, "move:" + move + " countValue:" + countValue +
                " getMeasuredWidth():" + switchGrag.getMeasuredWidth()
              + " getWidth():" + switchGrag.getWidth() + " countValue2:" +countValue2);

        if (move < 0) {
            move = 0;
        } else if (move > countValue2) {
            Log.d(TAG, "移動到最右邊....");
            move = countValue2;
        }
        // switchGrag.setPadding(move, 0, 0, 0);
        setPaddingAction(move);
    }

    /**
     * 注意!這個是當前MySwitch2 ViewGroup的Touch事件
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }

    /**
     * 此方法並不去繪製任何東西,Android自動回去繪製的
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    /**
     * 是否能夠點擊
     */
    private boolean isClick = true;

    @Override
    public void onClick(View v) {
        Log.d(TAG, "onClick() >>>>>>>>>>>>>>>> run");
        Log.d(TAG, "onClick() isClick:" + isClick);
        if (isClick) {
            if (!switchStatus) {
                // 說明是關閉狀態,我要打開
                moveResult = (switchBackgroundWidth - switchGragWidth);
            } else {
                moveResult = 0;
            }
            switchGrag.setPadding(moveResult, 0, 0, 0);
        }
    }


    private float downX;
    private int moveResult;
    private float downTempX;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        boolean touchResult = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                touchResult = false;
                downTempX = downX;
                isClick = true;
                break;
            case MotionEvent.ACTION_MOVE:
                moveResult += (int) (event.getX() - downX);
                setScrollMove(moveResult);
                downX = event.getX();

                if (Math.abs(event.getX() - downTempX) > 5) {
                    // 說明在滑動,就onTouch來消費掉了,不給onClick點擊事件了
                    touchResult = true;
                    Log.d(TAG, "說明在滑動,就onTouch來消費掉了,不給onClick點擊事件了");
                    isClick = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                // int upLeft = 0;
                if (moveResult > (switchBackgroundWidth - switchGragWidth) / 2) {
                    moveResult = switchBackgroundWidth - switchGragWidth;
                } else if (moveResult < (switchBackgroundWidth - switchGragWidth) / 2) {
                    moveResult = 0;
                } else if (moveResult <= 0){
                    moveResult = 0;
                }
                setPaddingAction(moveResult);
                break;
            default:
                break;
        }
        return touchResult;
    }

    private void setPaddingAction(int value) {
        if (value > (switchBackgroundWidth - switchGragWidth) / 2) {
            switchStatus = true;
        } else if (value < (switchBackgroundWidth - switchGragWidth) / 2) {
            switchStatus = false;
        } else if (value <= 0){
            switchStatus = false;
        }
        switchGrag.setPadding(value, 0,0,0);
    }
}
相關文章
相關標籤/搜索