16

TL,博士;

ContextCompat.getColor()不使用夜间颜色 ( values-night/colors.xml),但在启用夜间模式时应该使用。

这是问题所在:

大家好,

所以我正在为我的 Android 应用程序实现一个深色主题,我称之为启用它: AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

我已经设置了颜色,values/colors.xml并且在values-night/colors.xml. 颜色根据 nightMode 变化很好,但是:

当我使用时ContextCompat.getColor(getApplicationContext(), R.id.myColor),它使用普通颜色(values/colors.xml)而不是夜间颜色(values-night/colors.xml)。

在我的build.gradle,我设置了这些:

implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0-beta01'

有人可以告诉我我做错了什么吗?

PS:我已经看过以下问题,它没有回答这个问题https://stackoverflow.com/questions/57779661/contextcompat-getcolor-method-ignores-night-mode

4

3 回答 3

24

我在夜间模式遇到了类似的问题。有些屏幕很好,但其他屏幕保持常规主题。最后,我发现我正在使用应用程序的上下文而不是当前的活动上下文来实例化一些视图。出于某种原因,应用程序的上下文不会跟踪此类信息。

因此,更新您的代码以使用当前的活动上下文而不是应用程序上下文。

供其他用户参考。避免:

ContextCompat.getColor(getApplicationContext(), R.id.myColor)

并使用:

// In a Activity
ContextCompat.getColor(this, R.id.myColor)

// In a View
ContextCompat.getColor(getContext(), R.id.myColor)

// In a Fragment (check against null because getContext can trigger a NPE
Context context = getContext()
if (context != null) {
    ContextCompat.getColor(context, R.id.myColor)
}
于 2019-10-10T14:11:12.390 回答
2

我遇到了和你类似的问题,我也发现问题的核心是应用程序没有像 Activity 这样的主题包装器。所以 W0rmH0le 的回答可以解决这个问题。但对我来说,有很多代码无法获取活动或视图的上下文。所以我想我们为什么不创建一个单例上下文包装器 nightMode 主题。有代码,它对我来说很好。

Resources res = getApplication().getResources();
Configuration configuration = new Configuration(res.getConfiguration());
int nightNode = AppCompatDelegate.getDefaultNightMode();
if (nightNode == AppCompatDelegate.MODE_NIGHT_NO) {
    configuration.uiMode = Configuration.UI_MODE_NIGHT_NO | (res.getConfiguration().uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
} else if (nightNode == AppCompatDelegate.MODE_NIGHT_YES) {
    configuration.uiMode = Configuration.UI_MODE_NIGHT_YES| (res.getConfiguration().uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
} else {
    configuration.uiMode = res.getConfiguration().uiMode;
}
mThemeContext = getApplication().createConfigurationContext(configuration);

然后你可以使用 mThemeContext 替换 Application,你可以找到正确的颜色跟随夜间模式。

于 2021-12-31T08:40:38.997 回答
0

应用程序上下文对当前主题或昼夜一无所知,因此如果您从应用程序上下文获取资源,您将在默认应用程序主题中获取资源。解决此问题的方法是使用活动/片段上下文,但在某些情况下,您可能没有活动或片段,而只有应用程序上下文。我创建了一个上下文包装类来将 Day & Night 主题添加到应用程序上下文中:

import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.ContextCompat

class ThemedContext(application: Context) {

    private val themedContext: Context

    init {
        val res: Resources = application.resources
        val configuration = Configuration(res.configuration)
        val filter = res.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK.inv()

        configuration.uiMode = when (AppCompatDelegate.getDefaultNightMode()) {
            AppCompatDelegate.MODE_NIGHT_NO -> Configuration.UI_MODE_NIGHT_NO or filter
            AppCompatDelegate.MODE_NIGHT_YES -> Configuration.UI_MODE_NIGHT_YES or filter
            else -> res.configuration.uiMode
        }

        themedContext = application.createConfigurationContext(configuration)
    }

    fun getColor(@ColorRes id: Int) = ContextCompat.getColor(themedContext, id)
    fun getDrawable(@DrawableRes id: Int) = ContextCompat.getDrawable(themedContext, id)
    //todo Add other getter methods as needed...
}

此代码已经过测试和工作。

于 2022-03-05T10:22:07.603 回答