Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use material 3 Switch in PreferenceFragmentCompat programmatically?

SwitchPreferenceCompat still retains the old Switch style, I know to be able to style it Material 3 in the following way:

theme.xml

<style name="Theme.Material3.Preference" parent="Theme.Material3.DayNight.NoActionBar">
    <item name="preferenceTheme">@style/MaterialPreferenceThemeOverlay</item>
</style>

<style name="MaterialPreferenceThemeOverlay" parent="PreferenceThemeOverlay">
    <item name="switchPreferenceCompatStyle">@style/Preference.SwitchPreferenceCompat</item>
</style>

<style name="Preference.SwitchPreferenceCompat" parent="Preference.SwitchPreferenceCompat.Material">
    <item name="android:widgetLayout">@layout/preference_widget_material_switch</item>
</style>

preference_widget_material_switch.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.materialswitch.MaterialSwitch
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/switchWidget"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:focusable="false"
    android:clickable="false"
    android:background="@null"/>

setting.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <SwitchPreferenceCompat
        android:defaultValue="true"
        android:key="pref_key"
        android:summary="Preference Summary"
        android:title="Preference Title" />
</PreferenceScreen>

enter image description here
But for some reason I have to build PreferenceFragment programmatically like this:

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    val context = preferenceManager.context
    val screen = preferenceManager.createPreferenceScreen(context)
    val notificationPreference = SwitchPreferenceCompat(context).apply {
        key = "pref_key"
        title = "Preference Title"
        summary="Preference Summary"
    }
    screen.addPreference(notificationPreference)
    preferenceScreen = screen
}

At this time, even if I have the ThemeOverlay above, the style of the switch is still old. enter image description here
So, how to use material 3 Switch in PreferenceFragmentCompat programmatically?

I'm guessing it might be possible to set the theme of SwitchPreferenceCompat via one of its constructors, but I don't know about Views, so can you guys help me?

SwitchPreferenceCompat(@NonNull Context context)  

SwitchPreferenceCompat(
    @NonNull Context context,
    @Nullable AttributeSet attrs
)  

SwitchPreferenceCompat(
    @NonNull Context context,
    @Nullable AttributeSet attrs,
    int defStyleAttr
)  

SwitchPreferenceCompat(
    @NonNull Context context,
    @Nullable AttributeSet attrs,
    int defStyleAttr,
    int defStyleRes
)
like image 494
bqliang Avatar asked Apr 30 '26 09:04

bqliang


1 Answers

If you don't want to add a new class for the Material 3 switches, you can override the used layout of the usual SwitchPreferenceCompat by following 2 simple steps:

https://medium.com/@cyb3rko/simple-implementation-of-material-3-switches-in-preferences-4b83ea3202d1


  1. Add the new switch layout to your project:
<?xml version="1.0" encoding="utf-8"?>
<!-- Derived from https://github.com/androidx/androidx/blob/005e9694795cee9a42375d80b0d813af9e700ac1/preference/preference/res/layout/preference_widget_switch_compat.xml -->
<!-- Thanks to https://stackoverflow.com/a/73782598/9077356 -->
<com.google.android.material.materialswitch.MaterialSwitch
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/switchWidget"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:focusable="false"
    android:clickable="false"
    android:background="@null" />
  1. Override the switch theming in your app theming:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    ...
    
    <style name="Preference.SwitchPreferenceCompat" parent="@style/Preference.SwitchPreferenceCompat.Material"
           tools:ignore="ResourceCycle">
        <item name="widgetLayout">@layout/preference_switch</item>
    </style>
    
    ...
</resources>

Now you can just use the usual SwitchPreferenceCompat in your preference screen like before:

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

    <SwitchPreferenceCompat
        app:title="Material 3 switch"
        app:summary="This is the new Material 3 switch" />

</PreferenceScreen>
like image 178
Cyb3rKo Avatar answered May 02 '26 23:05

Cyb3rKo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!