關於Switch的自定義樣式

關於Switch的自定義樣式

Switch是安卓4.0之後新增的控件,是CompoundButton的子類。其他常用的CompoundButton的子類有CheckBox,RadioButton,ToogleButton。可以看出他們都是有checked和unchecked兩種狀態的控件。

爲什麼要自定義樣式

得益於國內手機廠商的技術改造能力,如果使用默認的樣式,會呈現各式各樣。有的會顯示文字,有的不顯示文字,問題很多。統一的方法就是自定義樣式,況且大部分的國內RAM默認樣式都比較“土”。這裏我們要實現下圖的Switch樣式。
下面的樣式讀者一定不會陌生,這算是目前比較流行的Switch樣式,但是大部分的app都是使用的checkBox而不是地道的Switch。

1 2

遇到的問題和解決方法

  1. 通過查看源碼我們可以發現,Switch自定義樣式需要修改按鈕(thumb)和背景(track),按鈕裏面可以顯示狀態文字。
    所以博主獲取到一份複合要求的圖片之後,通過簡單的selector來進行實現,發現樣式不能讓人滿意。所以看了Switch的源碼之後,找到了解決辦法。
  2. Switch源碼分析(主要是onMeasure
        // 下面是計算指示按鈕的寬度
        // mThumbTestPaddig:Switch可以在指示按鈕顯示"on"或者"off"的文字,這個屬性是設置文字的padding。
        // 如果你使用9.png圖片作爲按鈕背景,出現按鈕扁平的情況,則需要合理設置這個值。
        final int maxTextWidth;
        if (mShowText) {
            maxTextWidth = Math.max(mOnLayout.getWidth(), mOffLayout.getWidth())
                    + mThumbTextPadding * 2;
        } else {
            maxTextWidth = 0;
        }

        // Adjust left and right padding to ensure there's enough room for the
        // thumb's padding (when present).
        int paddingLeft = padding.left;
        int paddingRight = padding.right;
        if (mThumbDrawable != null) {
            final Insets inset = mThumbDrawable.getOpticalInsets();
            paddingLeft = Math.max(paddingLeft, inset.left);
            paddingRight = Math.max(paddingRight, inset.right);
        }

        // 如果你自定義的Switch比你預期的寬度要寬的話,你需要了解一下下面這句。
        // 從下面這句我們可以看出Switch的寬度,還受限於一個switchMinWidth的屬性,
        // 如果你的背景小於這個值就會有比預期要寬的情況。
        // 可以在佈局文件裏面通過屬性android:switchMinWidth來設置這個屬性。
        final int switchWidth = Math.max(mSwitchMinWidth,       // 屬性設置的最小寬度
                2 * mThumbWidth + paddingLeft + paddingRight);  // 足夠顯示兩個狀態按鈕的寬度
        final int switchHeight = Math.max(trackHeight, thumbHeight);
        mSwitchWidth = switchWidth;
        mSwitchHeight = switchHeight;

通過了解上面的代碼我解決了我開發過程中出現的問題。

源碼

/layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <!--android:switchMinWidth="44dp":track使用的是寬度爲48dp的圓角方形,此處值不大於48dp都可以-->
    <!--android:thumbTextPadding="16dp":thumb使用的的半徑爲16dp的圓-->
    <!--這裏我們不需要thumb顯示文字-->
    <Switch
        android:id="@+id/mySwitch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:switchMinWidth="48dp"
        android:textOff=""
        android:textOn=""
        android:thumb="@drawable/thumb"
        android:thumbTextPadding="16dp"
        android:track="@drawable/track" />

</RelativeLayout>

/drawable/thumb.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"  android:drawable="@drawable/thumb_off" />
    <item android:state_checked="true"  android:drawable="@drawable/thumb_on" />
    <item                               android:drawable="@drawable/thumb_off" />

</selector>

/drawable/thumb_on.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring"
    android:innerRadius="0dp"
    android:innerRadiusRatio="1"
    android:thickness="15dp"
    android:thicknessRatio="2"
    android:useLevel="false">

    <!--半徑設置爲15dp是爲了讓邊界能夠顯示出一絲track-->

    <solid android:color="#ffffffff" />

</shape>

/drawable/thumb_off.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring"
    android:innerRadius="0dp"
    android:innerRadiusRatio="1"
    android:thickness="16dp"
    android:thicknessRatio="2"
    android:useLevel="false">

    <stroke android:width="1px"
        android:color="#bdbdbd"/>

    <solid android:color="#ffffffff" />

</shape>

/drawable/track.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true"  android:drawable="@drawable/track_on" />
    <item android:state_checked="true"  android:drawable="@drawable/track_on" />
    <item                               android:drawable="@drawable/track_off" />

</selector>

/drawable/track_on.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">

    <size android:height="34dp"
        android:width="48dp"/>
    <corners android:radius="17dp" />
    <gradient android:height="34dp" android:startColor="#4CD864" android:endColor="#4CD864"/>
</shape>

/drawable/tracl_off.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring"
    android:innerRadius="0dp"
    android:innerRadiusRatio="1"
    android:thickness="16dp"
    android:thicknessRatio="2"
    android:useLevel="false">

    <stroke android:width="1px"
        android:color="#bdbdbd"/>

    <solid android:color="#ffffffff" />

</shape>

完整項目下載

發佈了29 篇原創文章 · 獲贊 2 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章