首頁 > 軟體

Android自定義控制元件實現簡單滑動開關效果

2022-02-16 19:00:48

本文範例為大家分享了Android自定義控制元件實現簡單滑動開關的具體程式碼,供大家參考,具體內容如下

ToggleButton 滑動開關

專案概述

滑動開關是一個純粹的自定義控制元件,上面的按鈕會隨著我們的左右滑動而滑動,並且在狀態改變時通知使用者,效果如下圖1-9 所示,這也是應用中設定某些狀態資訊時最常見的控制元件,因此,我們有必要學習關於如何

自定義一個這樣的滑動開關。

滑動開關UI

佈局檔案為activity_main.xml,程式碼如下:res/layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:itheima="http://schemas.android.com/apk/res/com.itheima.togglebuttondemo"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    <com.itheima.togglebuttondemo.view.ToggleButton
        android:id="@+id/togglebutton"
        android:layout_width="wrap_content"
        android:layout_centerInParent="true"
        itheima:SwitchBtnBackgroud="@drawable/switch_background"
        itheima:SlidBtnBackgroud="@drawable/slide_button_background"
        itheima:CurrentState="false"
        android:layout_height="wrap_content"/>
</RelativeLayout>

在activity_main.xml 佈局中引入如下名稱空間:

xmlns:itheima=”http://schemas.android.com/apk/res/com.itheima.togglebuttondemo”,com.itheima.togglebuttondemo 是包名,itheima 是自定義的命名控制元件名,可以任取名字,也可以使用類名。

上面的佈局主要是引入com.itheima.togglebuttondemo.view.ToggleButton 類和自定義屬性的使用。新增自定義屬性,在values 目錄下建立attrs.xml 檔案,具體程式碼如檔案所示:

res/values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="ToggleButton">
        <!-- 滑動開關背景圖片屬性-->
        <attr
            name="SwitchBtnBackgroud"
            format="reference"/>
        <!-- 滑動塊背景圖片屬性-->
        <attr
            name="SlidBtnBackgroud"
            format="reference"/>
        <!-- 滑動開關的狀態-->
        <attr
            name="CurrentState"
            format="boolean"/>
    </declare-styleable>
</resources>

attrs.xml 檔案目錄結構如下圖所示:

滑動開關業務邏輯實現

下拉選擇框activity 介面,MainActivity.java 程式碼如下:com/itheima/MySwitch/MainActivity

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ToggleButton togglebutton = (ToggleButton) findViewById(R.id.togglebutton);
        //設定滑動開關的背景圖片
        // togglebutton.setSwitchBtnBackgroudResource(R.drawable.switch_background);
        //設定滑動塊的背景圖片
        // togglebutton.setSlidBtnBackgroudResource(R.drawable.slide_button_background);
        //設定滑動開關的預設狀態
        // togglebutton.setCurrentState(true);
        //設定滑動開關狀態改變監聽
        Togglebutton.setToggleBtnStateChangeListener(new ToggleBtnStateChangeListener() {
            @Override
            public void onToggleBtnStateChange(boolean currentState) {
                if (currentState) {
                    Toast.makeText(getApplicationContext(), "開關開啟", 0).show();
                }else{
                    Toast.makeText(getApplicationContext(), "開關關閉", 0).show();
                }
            }
        });
    }
}

自定義的滑動開關ToggleButton 類的實現,具體程式碼如檔案所示:com/itheima/MySwitch/MainActivity

public class ToggleButton extends View {
    private Bitmap  switchBitmap;//滑動開關的背景圖片
    private Bitmap  slidBitmap;//滑動塊的背景圖片
    private boolean currentState;
    private int     currentX;//手指觸控點的X 值
    private boolean isTouching = false;
    private ToggleBtnStateChangeListener mToggleBtnStateChangeListener;//狀態改變監聽器
    //在xml 中參照該控制元件時,呼叫該方法
    public ToggleButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        String namespace = "http://schemas.android.com/apk/res/com.itheima.togglebuttondemo";
        currentState = attrs.getAttributeBooleanValue(namespace, "CurrentState", false);
        int switchBtnBackgroudId =
                attrs.getAttributeResourceValue(namespace, "SwitchBtnBackgroud", -1);
        int slidBtnBackgroudId =
                attrs.getAttributeResourceValue(namespace, "SlidBtnBackgroud", -1);
        setSwitchBtnBackgroudResource(switchBtnBackgroudId);
        setSlidBtnBackgroudResource(slidBtnBackgroudId);
    }
    //在程式碼中建立該控制元件時,呼叫該構造方法
    public ToggleButton(Context context) {
        super(context);
    }
    //設定滑動開關的背景圖片
    public void setSwitchBtnBackgroudResource(int switchBackground) {
        switchBitmap = BitmapFactory.decodeResource(getResources(), switchBackground);
    }
    // 為了可以高度自定義和增強可延伸性,我們可以給其建立一個自定義控制元件底部背景了一個方法
    // 設定滑動塊的背景圖片
    public void setSlidBtnBackgroudResource(int slideButtonBackground) {
        slidBitmap = BitmapFactory.decodeResource(getResources(), slideButtonBackground);
    }
    //設定滑動開關的預設狀態
    public void setCurrentState(boolean b) {
        currentState = b;
    }
    // 1、測量滑動開關的寬高
    // 測量控制元件的寬高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(switchBitmap.getWidth(), switchBitmap.getHeight());
    }
    // 2、繪製,畫出我們的滑動開關
    //canvas:畫布,將圖形繪製在canvas,才能顯示到螢幕上
    @Override
    protected void onDraw(Canvas canvas) {
        //繪製滑動開關的背景圖片
        canvas.drawBitmap(switchBitmap, 0, 0, null);
        //繪製滑動塊的背景圖片
        if(isTouching){//手指觸控的時候,根據currentx 的值來繪製滑動塊
            //根據手指的X 值,來繪製滑動塊圖片
            int left = currentX - slidBitmap.getWidth()/2;
            if(left < 0){//設定左邊界
                left = 0;
            }else if(left > (switchBitmap.getWidth() - slidBitmap.getWidth())){//設定右邊界
                left = switchBitmap.getWidth() - slidBitmap.getWidth();
            }
            canvas.drawBitmap(slidBitmap, left, 0, null);
        }else{ // 手指離開控制元件的時候,根據狀態來繪製滑動塊
            // 根據狀態值,來繪製滑動塊
            if(currentState){ //當前為true,開關開啟,滑動塊顯示在最右邊
                canvas.drawBitmap(slidBitmap,switchBitmap.getWidth() - slidBitmap.getWidth(),
                        0, null);
            }else{//當前為false,開關關閉,滑動塊顯示在最左邊
                canvas.drawBitmap(slidBitmap, 0, 0, null);
            }
        }
    }
    //當控制元件被觸控後,會呼叫該方法
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://手指按下
                isTouching = true;
                currentX = (int) event.getX();
                break;
            case MotionEvent.ACTION_MOVE://手指滑動
                isTouching= true;
                currentX = (int) event.getX();
                break;
            case MotionEvent.ACTION_UP://手指擡起
                isTouching = false;
                currentX = (int) event.getX();
                int center = switchBitmap.getWidth()/2;
                //當滑動塊中心點大於滑動開關背景圖片的中心線時,顯示到右邊,當前狀態為true
                boolean state = currentState;
                currentState = currentX > center;
                if(mToggleBtnStateChangeListener !=null&&state != currentState ){
                    mToggleBtnStateChangeListener.onToggleBtnStateChange(currentState);
                }
                break;
            default:
                break;
        }
        invalidate(); //強制讓控制元件重新繪製,ondraw;
        return true; //自己處理觸控事件
    }
    public void setToggleBtnStateChangeListener(ToggleBtnStateChangeListenerlistener){
        this.mToggleBtnStateChangeListener = listener;
    }
    // 定義滑動開關狀態改變的回撥介面
    public interface ToggleBtnStateChangeListener{
        void onToggleBtnStateChange(boolean currentState);
    }
}

執行程式,效果圖如圖1-11 所示。

知識點總結

1.通過setMeasuredDimension 方法,來設定自定義控制元件的寬高,見ToggleButton 類第42 行
2.View 可以通過invalidate()方法強制讓自己重新繪製,見ToggleButton 類第96 行
3.View 通過實現onTouchEvent 方法來處理手指觸控事件,見ToggleButton 類第72 行

自定義控制元件之自定義屬性

當我們使用自定義屬性來自定義控制元件時,一般分為以下幾個步驟進行設定:

1、在res 檔案的values 裡面建立attrs.xml,見檔案【1-10】attrs.xml
2、在attrs.xml,裡面定義我們需要的屬性,見檔案【1-10】attrs.xml 程式碼
3、在佈局檔案中使用自定義的屬性,注意要新增名稱空間,見檔案【1-9】activity_main.xml 第2 行
4、在構造方法中來獲取設定的屬性資料,見檔案【1-9】見ToggleButton 類第8~19 行

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com