You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PreferenceFragmentCompat中以代码方式使用Material 3 Switch?

代码构建PreferenceFragmentCompat时如何启用Material 3风格的SwitchPreferenceCompat

背景

我已了解通过XML配置可让SwitchPreferenceCompat使用Material 3风格:

1. 主题配置(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>

2. 自定义Switch布局(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"/>

3. XML定义Preference(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>

通过XML配置时,Switch能正常显示Material 3样式,但当我用代码构建PreferenceFragment时:

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
}

即便配置了主题,Switch还是旧版样式。

问题

如何在PreferenceFragmentCompat中通过代码方式使用Material 3风格的Switch?

我猜测可能需要通过SwitchPreferenceCompat的构造函数指定主题,但对视图相关知识不太熟悉,希望得到解答。SwitchPreferenceCompat的构造函数如下:

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
)

解决方案

方案1:用主题包装Context创建SwitchPreferenceCompat

直接使用preferenceManager.context可能未应用自定义的Preference主题,通过ContextThemeWrapper包装上下文,传入我们定义的MaterialPreferenceThemeOverlay主题:

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    val originalContext = preferenceManager.context
    // 用自定义Preference主题包装上下文
    val themedContext = ContextThemeWrapper(originalContext, R.style.MaterialPreferenceThemeOverlay)
    val screen = preferenceManager.createPreferenceScreen(originalContext)
    
    val notificationPreference = SwitchPreferenceCompat(themedContext).apply {
        key = "pref_key"
        title = "Preference Title"
        summary = "Preference Summary"
    }
    
    screen.addPreference(notificationPreference)
    preferenceScreen = screen
}

方案2:构造函数传入自定义样式参数

利用SwitchPreferenceCompat的多参构造函数,直接指定自定义的样式属性和资源:

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    val context = preferenceManager.context
    val screen = preferenceManager.createPreferenceScreen(context)
    
    val notificationPreference = SwitchPreferenceCompat(
        context,
        null,
        androidx.preference.R.attr.switchPreferenceCompatStyle, // 指定系统样式属性
        R.style.Preference_SwitchPreferenceCompat // 传入我们自定义的样式
    ).apply {
        key = "pref_key"
        title = "Preference Title"
        summary = "Preference Summary"
    }
    
    screen.addPreference(notificationPreference)
    preferenceScreen = screen
}

方案3:给宿主Activity指定正确主题

在AndroidManifest.xml中,给PreferenceFragmentCompat所在的Activity设置Theme.Material3.Preference主题,这样preferenceManager.context会自动继承该主题,代码创建的SwitchPreferenceCompat也会应用Material 3样式:

<activity
    android:name=".YourPreferenceActivity"
    android:theme="@style/Theme.Material3.Preference">
</activity>

内容的提问来源于stack exchange,提问作者bqliang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:45:27