当前位置: 首页 > 知识库问答 >
问题:

Android通过AppCompatPreferenceActivity模板设置夜间模式,取消点击首选项标题

叶嘉颖
2023-03-14

我的目标是:通过首选项设置夜间模式,并实时更新用户界面。

到目前为止:完成。但是当我点击回到标题的首选项屏幕时,我无法再次回到不同的首选项屏幕。

详细说明:在这一点上,我的设置非常简单。我遵循Android Studio(3.1.4)设置的SettingsActivity预设,拥有一个AppCompatPreferenceActivity模板。我有一个主屏幕和两个更深的屏幕。

我的第一个屏幕有两个选择:常规和关于。选择常规后,我加载一个带有一个开关首选项的通用首选项片段,即“夜间模式”。如果我设置它,它会实时切换主题,当我返回时,它也会在我的第一个设置屏幕上完成。

问题是:当我改变主题时,回到主设置屏幕,我尝试重新访问常规屏幕或关于屏幕,我不能再深入了!如果我将偏好切换为偶数,这样我就可以访问初始主题,就像什么都没发生一样。

设置活动类

class SettingsActivity : AppCompatPreferenceActivity() {

// To be used for live changes in night mode
private var mCurrentNightMode: Int = 0
private val TAG = "SettingsActivity"
private var mThemeId = 0

/**
 * Doing this hack to add my own actionbar on top since it wasn't there on its own
 */
override fun onPostCreate(savedInstanceState: Bundle?) {
    super.onPostCreate(savedInstanceState)
    Log.d(TAG, "onPostCreate")

    val root = findViewById<View>(android.R.id.list).parent.parent.parent as LinearLayout
    val bar = LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false) as Toolbar
    root.addView(bar, 0) // insert at top
    bar.setNavigationOnClickListener {finish()}
}

override fun setTheme(resid: Int) {
    super.setTheme(resid)
    mThemeId = resid
}

override fun onCreate(savedInstanceState: Bundle?) {
    if (delegate.applyDayNight() && (mThemeId != 0) ) {
        // If DayNight has been applied, we need to re-apply the theme for
        // the changes to take effect. On API 23+, we should bypass
        // setTheme(), which will no-op if the theme ID is identical to the
        // current theme ID.
        if (Build.VERSION.SDK_INT >= 23) {
            onApplyThemeResource(theme, mThemeId, false);
        } else {
            setTheme(mThemeId);
        }
    }
    super.onCreate(savedInstanceState)
    Log.d("SettingsActivity", "onCreate")
    setupActionBar()

    // Storing the current value so if we come back we'll check on postResume for any changes
    mCurrentNightMode = getCurrentNightMode();
}

// Comparing current and last known night mode value
private fun hasNightModeChanged(): Boolean {
    return mCurrentNightMode != getCurrentNightMode()
}

private fun getCurrentNightMode(): Int {
    return resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
}

override fun onPostResume() {
    super.onPostResume()

    // Self-explanatory. When I load back into this screen, if there's a change in the theme, load it back!
    if(hasNightModeChanged()) {
        recreate()
    }
}

/**
 * Set up the [android.app.ActionBar], if the API is available.
 */
private fun setupActionBar() {
    supportActionBar?.setDisplayHomeAsUpEnabled(true)
}

/**
 * {@inheritDoc}
 */
override fun onIsMultiPane(): Boolean {
    return isXLargeTablet(this)
}

/**
 * {@inheritDoc}
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
override fun onBuildHeaders(target: List<PreferenceActivity.Header>) {
    loadHeadersFromResource(R.xml.pref_headers, target)
}

/**
 * This method stops fragment injection in malicious applications.
 * Make sure to deny any unknown fragments here.
 */
override fun isValidFragment(fragmentName: String): Boolean {
    return PreferenceFragment::class.java.name == fragmentName
            || GeneralPreferenceFragment::class.java.name == fragmentName
            || DataSyncPreferenceFragment::class.java.name == fragmentName
            || NotificationPreferenceFragment::class.java.name == fragmentName
            || AboutFragment::class.java.name == fragmentName
}

/**
 * This fragment shows general preferences only. It is used when the
 * activity is showing a two-pane settings UI.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
class GeneralPreferenceFragment : PreferenceFragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        addPreferencesFromResource(R.xml.pref_general)
        setHasOptionsMenu(true)

        // Bind the summaries of EditText/List/Dialog/Ringtone preferences
        // to their values. When their values change, their summaries are
        // updated to reflect the new value, per the Android Design
        // guidelines.
        findPreference("night_mode").setOnPreferenceChangeListener { preference, newValue ->
            val booleanValue = newValue as Boolean

            if(booleanValue) {
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
            } else {
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
            }

            activity.recreate()
            true
        }
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        val id = item.itemId
        if (id == android.R.id.home) {
            startActivity(Intent(activity, SettingsActivity::class.java))
            return true
        }
        return super.onOptionsItemSelected(item)
    }
}
 .
 .
 .
 companion object {
 // (didn't change anything here)
 }

问题出现在我的“重新创建”通话中。这就像首选项列表的监听器为空或类似。

有人能帮忙吗?

编辑:简化,现在我所有的逻辑都在SettingsActivity类中,我不需要在抽象类中使用它

共有1个答案

汤嘉平
2023-03-14

我不敢相信我通过添加delayedRecreate而不是recreate解决了这个问题(尝试了与另一个问题不同的事情——这一个):

override fun onPostResume() {
    super.onPostResume()

    // Self-explanatory. When I load back into this screen, if there's a change in the theme, load it back!
    if(hasNightModeChanged()) {
        delayedRecreate()
    }
}

private fun delayedRecreate() {
    val handler = Handler()
    handler.postDelayed(this::recreate, 1)
}

然而,我真的不喜欢屏幕在重新创建时稍微延迟时的闪烁。如果有任何其他线索,我们将不胜感激!

 类似资料:
  • 获取设备夜间模式 接口说明 获取设备夜间模式 示例代码: Swift: RokidMobileSDK.device.getNightMode(device: RKDevice, completion: @escaping (_ error: RKError?, _ nightMode: SDKDeviceNightMode?) -> Void) Objc: RKDevice * device

  • 获取设备夜间模式 接口说明 获取设备夜间模式 参数说明 字段 类型 必须? 说明 deviceId String 是 设备ID 示例代码: String deviceId = "XXXXXX"; RokidMobileSDK.device.getNightMode(deviceId, new IGetDeviceNightMode() { @Override

  • 现在我们提供一个夜间模式,你只需要在 body 或者 .page 或者 .content 上加上 .theme-dark。它和其中所有子元素都会变成夜间模式。你也可以单独给 .bar 加上 .theme-dark,这样可以单独使标题栏或者工具栏变成夜间模式。 夜间模式最大的区别是他的背景变成了黑色,而前景色变成了白色。 夜间模式还处在测试阶段,可能会有某些组件在夜间模式下显示不正常。有任何问题都可

  • 本文向大家介绍Android夜间模式最佳实践,包括了Android夜间模式最佳实践的使用技巧和注意事项,需要的朋友参考一下 由于Android的设置中并没有夜间模式的选项,对于喜欢睡前玩手机的用户,只能简单的调节手机屏幕亮度来改善体验。目前越来越多的应用开始把夜间模式加到自家应用中,没准不久google也会把这项功能添加到Android系统中吧。 业内关于夜间模式的实现,有两种主流方案,各有其利弊

  • 关于首选项 首选项是关于您希望 Illustrator 如何工作的选项,包括显示、工具、标尺单位和导出信息。您的首选项存储在名为 “AIPrefs”(Windows) 或 “Adobe Illustrator Prefs”(Mac OS) 的文件中,每次您启动 Illustrator 时它也随之启动。要恢复 Illustrator 的默认设置,您可以删除或重命名首选项文件并重新启动 Illustr

  • 我是Android编程的新手,首先我想用SharedPreays做一个简单的选项菜单演示。我已经创建了基本的结构,但是我不知道如何将OnPreancceClickListener附加到Preation。尽管如此,我可以使用onSharedPreancceChanged方法,但是没有其他事件侦听器。(再次,我是初学者,所以我不知道为什么会这样。) 我已经阅读了有关创建菜单步骤的文档:https://