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
)
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.
You can use the below website to generate style for your Switch. http://android-holo-colors.com/
And then you can use following libraries to custom implementation of the regular Switch. These libraries also include SwitchPreference alternative.
https://github.com/BoD/android-switch-backport
https://github.com/ankri/SwitchCompatLibrary
One way of doing this is to subclass the SwitchPreference and override the onBindView method. In doing so, you'll want to still call super.onBindView(view) in that method, but then find the Switch in the child views and style it as appropriate:
package com.example;
import android.annotation.SuppressLint;
import android.content.Context;
import android.preference.SwitchPreference;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
import com.example.R;
public class CustomSwitchPreference extends SwitchPreference {
@SuppressLint("NewApi")
public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomSwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSwitchPreference(Context context) {
super(context);
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
Switch theSwitch = findSwitchInChildviews((ViewGroup) view);
if (theSwitch!=null) {
//do styling here
theSwitch.setThumbResource(R.drawable.new_thumb_resource);
}
}
private Switch findSwitchInChildviews(ViewGroup view) {
for (int i=0;i<view.getChildCount();i++) {
View thisChildview = view.getChildAt(i);
if (thisChildview instanceof Switch) {
return (Switch)thisChildview;
}
else if (thisChildview instanceof ViewGroup) {
Switch theSwitch = findSwitchInChildviews((ViewGroup) thisChildview);
if (theSwitch!=null) return theSwitch;
}
}
return null;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With