ContextCompat.getColor() 忽略夜间模式
ContextCompat.getColor() ignore NightMode
TL,DR;
ContextCompat.getColor()
不使用夜间颜色 (values-night/colors.xml
),但在启用夜间模式时应该使用。
问题是:
大家好,
所以我正在为我的 Android 应用程序实现一个深色主题,我调用它来启用它:
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
我在 values/colors.xml
中设置了颜色,在 values-night/colors.xml
中设置了深色版本。颜色根据夜间模式变化很好,但是:
当我使用 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 : 我已经看过下面的问题,它没有回答这个问题
我在使用夜间模式时遇到了类似的问题。有些屏幕很好,但其他屏幕保持常规主题。最后,我发现我正在使用应用程序的上下文而不是当前的 activity 上下文来实例化一些视图。出于某种原因,应用程序的上下文不会跟踪此类信息。
因此,更新您的代码以使用当前的 activity 上下文而不是应用程序上下文。
供其他用户参考。避免:
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)
}
我遇到了和你类似的问题,我也发现问题的核心是应用程序没有像Activity这样的主题包装器。所以 W0rmH0le 的回答可以解决这个问题。但对我来说,有很多代码无法获取 activity 或视图的上下文。所以我想我们为什么不创建一个单例上下文包装器 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,你就可以在夜间模式下找到合适的颜色。
应用上下文对当前主题或day/night一无所知,因此如果您从应用上下文获取资源,您将在默认应用主题中获取资源。此问题的解决方案是使用 activity/fragment 上下文,但在某些情况下,您可能没有 activity 或片段,只有应用程序上下文。
我创建了一个上下文包装器 class 以将 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...
}
此代码已经过测试并有效。
TL,DR;
ContextCompat.getColor()
不使用夜间颜色 (values-night/colors.xml
),但在启用夜间模式时应该使用。
问题是:
大家好,
所以我正在为我的 Android 应用程序实现一个深色主题,我调用它来启用它:
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
我在 values/colors.xml
中设置了颜色,在 values-night/colors.xml
中设置了深色版本。颜色根据夜间模式变化很好,但是:
当我使用 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 : 我已经看过下面的问题,它没有回答这个问题
我在使用夜间模式时遇到了类似的问题。有些屏幕很好,但其他屏幕保持常规主题。最后,我发现我正在使用应用程序的上下文而不是当前的 activity 上下文来实例化一些视图。出于某种原因,应用程序的上下文不会跟踪此类信息。
因此,更新您的代码以使用当前的 activity 上下文而不是应用程序上下文。
供其他用户参考。避免:
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)
}
我遇到了和你类似的问题,我也发现问题的核心是应用程序没有像Activity这样的主题包装器。所以 W0rmH0le 的回答可以解决这个问题。但对我来说,有很多代码无法获取 activity 或视图的上下文。所以我想我们为什么不创建一个单例上下文包装器 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,你就可以在夜间模式下找到合适的颜色。
应用上下文对当前主题或day/night一无所知,因此如果您从应用上下文获取资源,您将在默认应用主题中获取资源。此问题的解决方案是使用 activity/fragment 上下文,但在某些情况下,您可能没有 activity 或片段,只有应用程序上下文。 我创建了一个上下文包装器 class 以将 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...
}
此代码已经过测试并有效。