Custom SwitchPreference in Android

micnoy picture micnoy · Jan 20, 2014 · Viewed 18.2k times · Source

How to set a custom style or other background selector drawable for the SwitchPreference widget in Android?

(Note: not the regular Switch widget, I mean the standart SwitchPreference widget that used in PreferenceActivity / PreferenceFragment)

Answer

Mike picture Mike · Feb 18, 2014

You have to create a custom layout for the switch itself and you can apply it dynamically like.

preference.setWidgetLayoutResource(R.layout.custom_switch);

But I'll go into details and show you exactly how to achieve this.

So, you define your preference in an xml file like preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
    <PreferenceCategory android:title="YOUR_CATEGORY_TITLE" >
        <SwitchPreference
            android:key="SWITCH"
            android:title="YOUR_TITLE_FOR_SWITCH" />
    </PreferenceCategory>
</PreferenceScreen>

Then read it in the onCreate() method inside your PreferenceActivty class:

    SwitchPreference pref = (SwitchPreference) findPreference(getString(R.string.SWITCH));
    //pref.setChecked(true); // You can check it already if needed to true or false or a value you have stored persistently
    pref.setWidgetLayoutResource(R.layout.custom_switch); // THIS IS THE KEY OF ALL THIS. HERE YOU SET A CUSTOM LAYOUT FOR THE WIDGET
    pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            // Here you can enable/disable whatever you need to
            return true;
        }
    });

The custom_switch layout looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Switch xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_switch_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:textColor="@android:color/white"
    android:textIsSelectable="false"
    android:textSize="18sp"
    android:textStyle="bold"
    android:track="@drawable/switch_track" 
    android:thumb="@drawable/switch_thumb"/>

And for the switch you'll have 2 selectors for the track and thumb properties. The drawables for these selectors can be generated with the Android Holo Color Generator, which was suggested by tasomaniac. In this case, all you have to do, is to copy the content of the generated drawable folders(only for the drawable-hdpi, drawable-mdpi, drawable-xhdpi, drawable-xxhdpi). But you can create custom views for each state you need.

Here is how these selectors will look like: switch_track:

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

    <item android:drawable="@drawable/switch_bg_focused" android:state_focused="true"/>
    <item android:drawable="@drawable/switch_bg"/>

</selector>

switch_thumb:

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

     <item android:drawable="@drawable/switch_thumb_disabled" android:state_enabled="false"/>
     <item android:drawable="@drawable/switch_thumb_pressed" android:state_pressed="true"/>
     <item android:drawable="@drawable/switch_thumb_activated" android:state_checked="true"/>
     <item android:drawable="@drawable/switch_thumb"/>

</selector>

And that's pretty much it. This solution helped me out. If I omitted something, please let me know and I'll correct the issues.