Search code examples
androidstylesandroid-preferencesswitchpreferencematerial-you

New Android 12+ MaterialSwitch and androidx.preference


So i'm updating my apps to fully support Monet and Material You guidelines, and the official site mentions a new design for the switches. I used it, and that's the result:

MaterialSwitch in the app

I have a preference screen using Androidx preferences library, latest version available at the time of writing, and the only way i found to theme the switches (except the manual theming, which makes no sense) is to use this line in the app's theme:

<item name="switchStyle">@style/Widget.Material3.CompoundButton.MaterialSwitch</item>

And using SwitchPreferenceCompat (it doesn't work in the regular SwitchPreference) this is what i get:

Switch in preference

Regardless of the width (which is different, but can be changed) the disabled state is completely different and doesn't match the rest of the app. Why? and most importantly, why do they suggest to use a library which:

  1. Doesn't support Material You out of the box
  2. Doesn't support any new Material3 component
  3. It's hard to properly customize in general

?

I don't want to be too critical, but this is out of my understanding.

EDIT: at the moment, i'm using switchCompat everywhere, to make the app uniform. Looking at the system apps, i can find 4 different type of switches: a custom switch similar to the second screenshot, the old one and the two types in this question. That's hella confusing.


Solution

  • I understand Google stance on this, they don't want to make androidx.* packages dependent to Material library itself, maybe they should provide a separate preference package but this time with fully Material widgets.

    In order to have the brand new MaterialSwitch of Material 1.7.0 with preference, I've overridden its widgetLayout with a custom layout by android:widgetLayout="@layout/preference_material_switch" (in fact I applied that programmatically like .widgetLayoutResource = R.layout.preference_material_switch) and put the following on preference_material_switch.xml layout file,

    <?xml version="1.0" encoding="utf-8"?>
    <!-- Derived from https://github.com/androidx/androidx/blob/8cb282cc/preference/preference/res/layout/preference_widget_switch_compat.xml -->
    <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:background="@null"
        android:clickable="false"
        android:focusable="false" />
    

    Update: Alternative solution rather than adding android:widgetLayout= to each switch is to add the following to your base theme,

             <item name="preferenceTheme">@style/AppPreferenceThemeOverlay</item>
    

    Then adding the following styles also,

        <style name="AppPreferenceThemeOverlay" parent="@style/PreferenceThemeOverlay">
            <item name="switchPreferenceCompatStyle">@style/AppSwitchPreference</item>
        </style>
    
        <style name="AppSwitchPreference" parent="@style/Preference.SwitchPreferenceCompat.Material">
            <item name="widgetLayout">@layout/preference_material_switch</item>
        </style>
    

    And here is the result,

    enter image description here