Search code examples
androidxpreferencespreferenceactivityswitchpreference

Custom SwitchPreferenceCompat in androidx


I'm trying to change default switch thumb in preference screen to my custom. I've tried different solutions found here but none of them working. My last try was to create a custom layout but the problem is that I can't properly add switch to that layout. Can't really add androidx.appcompat.widget.SwitchCompat because of the id (@android:id/switch_widget requires API level 24 (current min is 21) or with other suggested id: Cannot resolve symbol '@android:id/switchWidget'). root_preferences.xml (part):

<PreferenceCategory app:title="@string/confidentiality"
    android:layout="@layout/preferences_category">

    <SwitchPreferenceCompat
        android:layout="@layout/switch_preference_compat"
        app:key="show_contacts"
        app:title="@string/contact_information"
        app:singleLineTitle="false"
        app:defaultValue="true"
        app:iconSpaceReserved="false"/>
</PreferenceCategory>

switch_preference_compat.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:gravity="center_vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:orientation="vertical">

        <TextView
            android:id="@android:id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/ks_font_data"
            android:textSize="18sp"/>

        <TextView
            android:id="@android:id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="16sp"/>

    </LinearLayout>

    <androidx.appcompat.widget.SwitchCompat
        android:id="@android:id/switchWidget" <--- error here
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

I tried styles but it also didn't work well. I want my thumb looks like this[my custom switch][1] [1]: https://i.sstatic.net/Js5vb.png


Solution

  • So after a few hours I was able to find out how to do that. Posting this answer so it may help somebody save their time. In root_preferences.xml there is android:widgetLayout property where you can set custom layout for SwitchPreferenceCompat:

        <SwitchPreferenceCompat
            android:widgetLayout="@layout/switch_preference_compat"
            app:key="show_contacts"
            app:title="@string/contact_information"
            app:singleLineTitle="false"
            app:defaultValue="true"
            app:iconSpaceReserved="false"/>
    

    switch_preference_compat.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="horizontal"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="8dp"
            android:orientation="vertical">
    
            <TextView
                android:id="@android:id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="18sp"/>
    
            <TextView
                android:id="@android:id/summary"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp"/>
    
        </LinearLayout>
    
        <androidx.appcompat.widget.SwitchCompat
            android:id="@+id/switchWidget"
            android:thumb="@drawable/thumb"
            app:track="@drawable/track"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    </LinearLayout> 
    

    there is where you put your drawables for custom thumb and track. Mine looks so: thumb.xml:

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

    track.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:state_checked="false">
            <shape android:shape="rectangle">
                <solid android:color="#dedede"/>
                <corners android:radius="100sp"/>
                <stroke android:color="#dedede"
                    android:width="1dp"/>
            </shape>
        </item>
    
        <item android:state_checked="true">
            <shape android:shape="rectangle">
                <solid android:color="#9dcbb5"/>
                <corners android:radius="100sp"/>
            </shape>
        </item>
    
    </selector>