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

求助:如何通过SwitchPreferenceCompat动态将所有Fragment背景设为红色?

需求与问题

我想通过SwitchPreferenceCompat把应用内所有Fragment的背景色设为红色,但在编写监听代码和MainActivity相关逻辑时遇到了麻烦。我试过一些操作,但不太清楚怎么写正确的监听代码,也不知道怎么在MainActivity里合理运用。我不需要完整的解决方案,只想要方向上的指引。


相关代码

Preferences XML

<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <PreferenceCategory android:title="Game Settings">
        <SeekBarPreference
            android:defaultValue="10"
            android:key="pennyCount"
            android:max="20"
            android:summary="@string/starting_penny_count_new_game"
            android:title="@string/starting_penny_count"
            app:min="1"
            app:showSeekBarValue="true" />

        <SwitchPreferenceCompat
            android:key="fastAI"
            android:summary="@string/fast_ai_summary"
            android:title="@string/fast_ai" />
    </PreferenceCategory>

    <PreferenceCategory android:title="Theme Settings">
        <DropDownPreference
            android:defaultValue="AppTheme"
            android:entries="@array/themes"
            android:entryValues="@array/theme_values"
            android:key="theme"
            android:title="@string/app_theme"
            app:useSimpleSummaryProvider="true" />

        <ListPreference
            android:defaultValue="System"
            android:entries="@array/theme_modes"
            android:entryValues="@array/theme_mode_values"
            android:key="themeMode"
            android:title="@string/theme_mode"
            app:useSimpleSummaryProvider="true" />
    </PreferenceCategory>

    <PreferenceCategory android:title="About the App">
        <Preference
            android:key="credits"
            android:summary="@string/about_app_summary"
            android:title="@string/about_penny_drop" />
    </PreferenceCategory>
    <SwitchPreferenceCompat
        android:defaultValue="false"
        android:key="switchRed"
        android:title="Turn Background Color Red"
        app:theme="@style/SwitchTheme"/>
</PreferenceScreen>

MainActivity.kt

package dev.mfazio.pennydrop

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.style.BackgroundColorSpan
import android.view.Menu
import android.view.MenuItem
import android.widget.Switch
import androidx.appcompat.app.AppCompatDelegate
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.onNavDestinationSelected
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager
import com.google.android.material.bottomnavigation.BottomNavigationView

class MainActivity : AppCompatActivity() {

    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        val prefs =
            PreferenceManager.getDefaultSharedPreferences(this)

        val themeId = when (prefs.getString("theme", "AppTheme")) {
            "Crew" -> R.style.Crew
            "FTD" -> R.style.FTD
            "GPG" -> R.style.GPG
            "Hazel" -> R.style.Hazel
            "Kotlin" -> R.style.Kotlin
            else -> R.style.AppTheme
        }

        setTheme(themeId)


        val nightMode = when (prefs.getString("themeMode", "")) {
            "Light" -> AppCompatDelegate.MODE_NIGHT_NO
            "Dark" -> AppCompatDelegate.MODE_NIGHT_YES
            else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
        }

        AppCompatDelegate.setDefaultNightMode(nightMode)

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.containerFragment) as NavHostFragment
        this.navController = navHostFragment.navController

        val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav)
        bottomNav.setupWithNavController(this.navController)

        val appBarConfiguration = AppBarConfiguration(bottomNav.menu)
        setupActionBarWithNavController(this.navController, appBarConfiguration)
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        super.onCreateOptionsMenu(menu)

        menuInflater.inflate(R.menu.options, menu)

        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean =
        if (this::navController.isInitialized) {
            item.onNavDestinationSelected(this.navController) ||
                super.onOptionsItemSelected(item)
        } else false

    override fun onSupportNavigateUp(): Boolean =
        (this::navController.isInitialized && this.navController.navigateUp()) ||
            super.onSupportNavigateUp()
}

SettingsFragment.kt

package dev.mfazio.pennydrop.fragments

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatDelegate
import androidx.navigation.fragment.findNavController
import androidx.preference.*
import dev.mfazio.pennydrop.R

class SettingsFragment : PreferenceFragmentCompat() {
    override fun onCreatePreferences(
        savedInstanceState: Bundle?,
        rootKey: String?
    ) {
        setPreferencesFromResource(R.xml.preferences, rootKey)

        val themePreference = findPreference<DropDownPreference?>("theme")
        val themeModePreference = findPreference<ListPreference?>("themeMode")
        val creditsPreference = findPreference<Preference?>("credits")
        val switchPreference = findPreference<SwitchPreferenceCompat>("switchRed")


        themePreference?.onPreferenceChangeListener =
            Preference.OnPreferenceChangeListener { _, _ ->

                activity?.recreate()

                true
            }

        themeModePreference?.setDefaultValue(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)

        themeModePreference?.onPreferenceChangeListener =
            Preference.OnPreferenceChangeListener { _, newValue ->
                val nightMode = when (newValue?.toString()) {
                    "Light" -> AppCompatDelegate.MODE_NIGHT_NO
                    "Dark" -> AppCompatDelegate.MODE_NIGHT_YES
                    else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
                }

                AppCompatDelegate.setDefaultNightMode(nightMode)
                true
            }

        creditsPreference?.onPreferenceClickListener =
            Preference.OnPreferenceClickListener { _ ->
                this.findNavController().navigate(R.id.aboutFragment)
                true
            }
    }
}

Styles XML

<resources>
    <style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="colorSurface">@color/nightLightGray</item>
    </style>

    <style name="Kotlin" parent="AppTheme">
        <item name="colorPrimary">@color/kotlinBlue</item>
        <item name="colorPrimaryDark">@color/kotlinPurple</item>
        <item name="colorAccent">@color/kotlinOrange</item>
    </style>

    <style name="Crew" parent="AppTheme">
        <item name="colorPrimary">@color/crewBlue</item>
        <item name="colorPrimaryDark">@color/crewLightBlue</item>
        <item name="colorAccent">@color/crewGold</item>
        <item name="colorSurface">@color/crewBlue</item>
    </style>

    <style name="FTD" parent="AppTheme">
        <item name="colorPrimary">@color/ftdGreen</item>
        <item name="colorPrimaryDark">@color/ftdGreen</item>
        <item name="colorAccent">@color/ftdBlue</item>
    </style>

    <style name="GPG" parent="AppTheme">
        <item name="colorPrimary">@color/packGreen</item>
        <item name="colorPrimaryDark">@color/packGreen</item>
        <item name="colorAccent">@color/packGold</item>
        <item name="colorSurface">@color/packGreenDark</item>
    </style>

    <style name="Hazel" parent="AppTheme">
        <item name="colorPrimary">@color/hazelBlue</item>
        <item name="colorPrimaryDark">@color/hazelDarkBlue</item>
        <item name="colorAccent">@color/hazelPink</item>
    </style>

    <style name="SwitchTheme" parent="AppTheme">
        <item name="android:colorBackground">#FF0000</item>
    </style>

</resources>

实现方向指引
  • 给开关添加状态监听:在SettingsFragment中找到switchRed实例,设置onPreferenceChangeListener。开关状态变化时,Preference会自动把布尔值保存到SharedPreferences,你只需要在回调里触发后续的背景更新逻辑(比如通知当前Fragment刷新,或者直接更新容器背景)。
  • 统一Fragment背景设置逻辑:
    • 推荐创建BaseFragment作为所有Fragment的父类,在BaseFragment的onViewCreated或onResume方法中,读取SharedPreferences里的switchRed状态,然后给Fragment的根View设置对应的背景色(红色或默认色)。
    • 也可以直接给MainActivity中的Fragment容器设置背景,但要注意Fragment布局是否有自己的背景覆盖容器。
  • MainActivity配合更新:可以给NavController添加addOnDestinationChangedListener,每次Fragment切换时,读取开关状态并更新当前Fragment的背景,或者更新容器背景。
  • 避免不必要的Activity重建:不像主题切换,背景色更新不需要重建Activity,直接更新View的背景属性即可,这样更高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 03:54:28