天天看點

自定義view-Android 簡單的滑動開關 ToggleButton

閑的沒事,寫一個自定義的滑動開關按鈕ToggleButton

按鈕圖可以使用圖檔或者xml繪制的drawable檔案,demo中使用的是預設的,可以直接替換成自己需要的。

效果:

自定義view-Android 簡單的滑動開關 ToggleButton

使用很簡單

1.将toggle-1.0.arr檔案放入libs目錄下(aar檔案可以直接在下面貼的github中下載下傳)

2.在build.gradle中加入依賴

implementation(name: 'toggle-1.0', ext: 'aar')
           

以上兩步完成就可以使用了

1.在xml布局中使用

xmlns:app="http://schemas.android.com/apk/res-auto"
<com.lange.toggle.ToggleButton
    android:id="@+id/btn_toggle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:btn_open_bg="@drawable/toggle_open_background"//自己替換打開時的背景圖或圖檔
    app:btn_close_bg="@drawable/toggle_close_background"//自己替換關閉時的背景圖或圖檔
    app:btn_slide_bg="@drawable/toggle_slide_background"//自己替換滑動按鈕的圖或圖檔
    app:btn_left_right_padding="1dp"//按鈕距離背景圖左右的距離
	android:layout_centerInParent="true"/>
           

2.activitu中使用

ToggleButton btn_toggle = findViewById(R.id.btn_toggle);
    //這是方式2,方式1可以在xml布局檔案中直接設定開關圖檔
    //btn_toggle.setToggleButtonOpenBackgroundResId(R.mipmap.switch_background);//設定滑動按鈕背景
    //btn_toggle.setToggleButtonCloseBackgroundResId(R.mipmap.switch_background);//設定滑動按鈕背景
    //btn_toggle.setToggleButtonSlideResId(R.mipmap.slide_button_background);//設定滑動按鈕圖
    //btn_toggle.setToggleButtonState(ToggleButton.ToggleButtonState.Close);//設定開關狀态
    //回調監聽狀态
    btn_toggle.setOnToggleStateChangeListener(new ToggleButton.OnToggleStateChangeListener() {
        @Override
        public void onStateChange(ToggleButton.ToggleButtonState state) {
            Toast.makeText(MainActivity.this, state== ToggleButton.ToggleButtonState.Close?"關":"開", Toast.LENGTH_SHORT).show();
        }
    });
           

大功告成!!!!就是這麼簡單!

下面貼上源碼,也可以直接去github上下載下傳源碼:github位址

/**
 * 自定義滑動開關
 */
public class ToggleButton extends View {
    private Bitmap btn_open_bg;
    private Bitmap btn_close_bg;
    private Bitmap btn_slide_bg;
    private float leftOrRightPadding = 0;//設定觸摸按鈕左右邊距
    public enum ToggleButtonState{
        Open,Close;
    }
    //開關狀态變量
    private ToggleButtonState mCurrentState = ToggleButtonState.Close;
    /**
     * 在Java代碼中直接new一個CustomView執行個體的時候,會調用該構造函數
     * @param context
     */
    public ToggleButton(Context context) {
        this(context,null);
    }

    /**
     * 在xml中引用CustomView标簽的時候,會調用2參數的構造函數。
     * 這種方式通常是我們需要自定義View的屬性的時候,使用2參數的構造函數。
     */
    public ToggleButton(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public ToggleButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //加載資源
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ToggleButton);
        //設定xml中的背景圖
        int imgOpenBgId = a.getResourceId(R.styleable.ToggleButton_btn_open_bg,R.drawable.toggle_open_background);
        setToggleButtonOpenBackgroundResId(context,imgOpenBgId);
        int imgCloseBgId = a.getResourceId(R.styleable.ToggleButton_btn_close_bg,R.drawable.toggle_close_background);
        setToggleButtonCloseBackgroundResId(context,imgCloseBgId);
        //設定xml中的按鈕圖
        int imgSlideId = a.getResourceId(R.styleable.ToggleButton_btn_slide_bg,R.drawable.toggle_slide_background);
        setToggleButtonSlideResId(context,imgSlideId);
        //設定左右padding,自動轉成px
        leftOrRightPadding = a.getDimensionPixelSize(R.styleable.ToggleButton_btn_left_right_padding,0);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //設定view的大小區域
        setMeasuredDimension(btn_open_bg.getWidth(),btn_open_bg.getHeight());
    }

    private float currentX;//記錄滑動的x位置
    private boolean isSliding = false;//是否正在滑動
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                currentX = event.getX();
                isSliding = true;
                break;
            case MotionEvent.ACTION_MOVE:
                currentX = event.getX();
                isSliding = true;
                break;
            case MotionEvent.ACTION_UP:
                isSliding = false;
                if(event.getX()>btn_open_bg.getWidth()/2){
                    if(mCurrentState == ToggleButtonState.Close) {
                        //打開狀态
                        mCurrentState = ToggleButtonState.Open;
                        if (stateChangeListener != null) {
                            stateChangeListener.onStateChange(mCurrentState);
                        }
                    }
                }else {
                    if(mCurrentState == ToggleButtonState.Open){
                        //關閉狀态
                        mCurrentState = ToggleButtonState.Close;
                        if(stateChangeListener!=null){
                            stateChangeListener.onStateChange(mCurrentState);
                        }
                    }
                }
                /*if(mCurrentState == ToggleButtonState.Close) {
                    //打開狀态
                    mCurrentState = ToggleButtonState.Open;
                }else{
                    //關閉狀态
                    mCurrentState = ToggleButtonState.Close;
                }
                if (stateChangeListener != null) {
                    stateChangeListener.onStateChange(mCurrentState);
                }*/
                break;
        }
        invalidate();
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //設定背景
        canvas.drawBitmap(mCurrentState== ToggleButtonState.Open?btn_open_bg:btn_close_bg,0,0,null);
        int top = (btn_open_bg.getHeight()-btn_slide_bg.getHeight())/2;
        if(isSliding){
            //設定滑動開關
            float left = currentX-btn_slide_bg.getWidth()/2;
            if(left<leftOrRightPadding)left = leftOrRightPadding;
            if(left>btn_open_bg.getWidth()-btn_slide_bg.getWidth()-leftOrRightPadding){
                left = btn_open_bg.getWidth()-btn_slide_bg.getWidth()-leftOrRightPadding;
            }
            canvas.drawBitmap(btn_slide_bg,left,top,null);
        }else{
            int left = (int)leftOrRightPadding;
            if(mCurrentState== ToggleButtonState.Open){
                left = btn_open_bg.getWidth()-btn_slide_bg.getWidth()-left;
            }
            canvas.drawBitmap(btn_slide_bg,left,top,null);
        }
    }

    /**
     * 代碼設定開關的背景圖檔
     * @param resId
     */
    @SuppressLint("NewApi")
    public void setToggleButtonOpenBackgroundResId(Context context, int resId){
       // btn_bg = BitmapFactory.decodeResource(getResources(),resId);
        Drawable vectorDrawable = context.getDrawable(resId);
        btn_open_bg = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
                vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(btn_open_bg);
        vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        vectorDrawable.draw(canvas);
    }
    /**
     * 代碼設定開關的背景圖檔
     * @param resId
     */
    @SuppressLint("NewApi")
    public void setToggleButtonCloseBackgroundResId(Context context, int resId){
       // btn_bg = BitmapFactory.decodeResource(getResources(),resId);
        Drawable vectorDrawable = context.getDrawable(resId);
        btn_close_bg = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
                vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(btn_close_bg);
        vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        vectorDrawable.draw(canvas);
    }

    /**
     * 代碼設定開關的按鈕圖檔
     * @param resId
     */
    @SuppressLint("NewApi")
    public void setToggleButtonSlideResId(Context context,int resId){
        //btn_slide_bg = BitmapFactory.decodeResource(getResources(),resId);
        Drawable vectorDrawable = context.getDrawable(resId);
        btn_slide_bg = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
                vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(btn_slide_bg);
        vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        vectorDrawable.draw(canvas);
    }

    /**
     * 代碼設定開關狀态
     * @param state
     */
    public void setToggleButtonState(ToggleButtonState state){
        this.mCurrentState = state;
    }

    /**
     * 設定位移動畫
     * @param v
     * @param fromX
     * @param toX
     */
    private void setTranslationAnim(View v,int fromX,int toX){
        ObjectAnimator oa = ObjectAnimator.ofFloat(v,"translationX",fromX,toX,0,0);
        oa.setDuration(200);
        oa.start();
    }

    /**
     * 設定監聽
     */
    private OnToggleStateChangeListener stateChangeListener;
    public interface OnToggleStateChangeListener{
        void onStateChange(ToggleButtonState state);
    }
    public void setOnToggleStateChangeListener(OnToggleStateChangeListener stateChangeListener){
        this.stateChangeListener = stateChangeListener;
    }
}
           

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--自定義開關view-->
    <declare-styleable name="ToggleButton">
        <attr name="btn_open_bg" format="reference" />
        <attr name="btn_close_bg" format="reference" />
        <attr name="btn_slide_bg" format="reference" />
        <attr name="btn_left_right_padding" format="dimension" />
    </declare-styleable>
</resources>