and*_*per 9 android themes android-8.1-oreo android-9.0-pie android-10.0
在最近的Android版本中,自Android 8.1以来,该操作系统对主题的支持越来越多。更具体地说,是深色主题。
即使从用户的角度讨论了黑暗模式,但几乎没有为开发人员编写任何内容。
从Android 8.1开始,Google提供了某种深色主题。如果用户选择使用深色墙纸,则操作系统的某些UI组件将变为黑色(此处为文章)。
此外,如果您开发了动态壁纸应用程序,则可以告诉操作系统它具有哪种颜色(三种颜色),这也影响了操作系统的颜色(至少在基于Vanilla的ROM和Google设备上)。这就是为什么我什至制作了一个应用程序,该应用程序可以让您拥有任何墙纸,同时仍然可以选择颜色(此处)。这是通过调用notifyColorsChanged,然后将它们使用提供onComputeColors
从Android 9.0开始,现在可以选择要使用的主题:亮,暗或自动(基于墙纸):
而现在,在接近Android Q的情况下,它似乎走得更远了,但尚不清楚到什么程度。不知何故,一个名为“ Smart Launcher”的启动器已经骑在其上,可以直接使用其主题(此处的文章)。因此,如果启用暗模式(按此处的说明手动进行),则会显示该应用的设置屏幕,如下所示:
到目前为止,我唯一发现的就是以上文章,并且我正在关注这种主题。
我也知道如何请求操作系统使用动态壁纸来更改颜色,但这似乎在Android Q上正在改变,至少根据我在尝试时看到的内容(我认为这更多是基于一天中的时间) ,但不确定)。
是否有API可以获取操作系统要使用的颜色?
是否有某种API可以获取操作系统的主题?从哪个版本开始?
新的API是否也与夜间模式相关?它们如何一起工作?
是否有适合应用程序处理所选主题的API?这意味着,如果操作系统具有特定主题,那么当前的应用程序也可以吗?
Vit*_*aab 20
对 Charles Annic 回答的更简单的 Kotlin 方法:
fun Context.isDarkThemeOn(): Boolean {
return resources.configuration.uiMode and
Configuration.UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES
}
Run Code Online (Sandbox Code Playgroud)
and*_*per 10
好的,所以我知道这在最新版本的 Android (Q) 和之前的版本中通常是如何工作的。
似乎当操作系统创建 WallpaperColors 时,它也会生成颜色提示。在函数中WallpaperColors.fromBitmap,有一个对 的调用int hints = calculateDarkHints(bitmap);,这是 的代码calculateDarkHints:
/**
* Checks if image is bright and clean enough to support light text.
*
* @param source What to read.
* @return Whether image supports dark text or not.
*/
private static int calculateDarkHints(Bitmap source) {
if (source == null) {
return 0;
}
int[] pixels = new int[source.getWidth() * source.getHeight()];
double totalLuminance = 0;
final int maxDarkPixels = (int) (pixels.length * MAX_DARK_AREA);
int darkPixels = 0;
source.getPixels(pixels, 0 /* offset */, source.getWidth(), 0 /* x */, 0 /* y */,
source.getWidth(), source.getHeight());
// This bitmap was already resized to fit the maximum allowed area.
// Let's just loop through the pixels, no sweat!
float[] tmpHsl = new float[3];
for (int i = 0; i < pixels.length; i++) {
ColorUtils.colorToHSL(pixels[i], tmpHsl);
final float luminance = tmpHsl[2];
final int alpha = Color.alpha(pixels[i]);
// Make sure we don't have a dark pixel mass that will
// make text illegible.
if (luminance < DARK_PIXEL_LUMINANCE && alpha != 0) {
darkPixels++;
}
totalLuminance += luminance;
}
int hints = 0;
double meanLuminance = totalLuminance / pixels.length;
if (meanLuminance > BRIGHT_IMAGE_MEAN_LUMINANCE && darkPixels < maxDarkPixels) {
hints |= HINT_SUPPORTS_DARK_TEXT;
}
if (meanLuminance < DARK_THEME_MEAN_LUMINANCE) {
hints |= HINT_SUPPORTS_DARK_THEME;
}
return hints;
}
Run Code Online (Sandbox Code Playgroud)
然后寻找getColorHints那个WallpaperColors.java,我在以下位置找到了updateTheme函数StatusBar.java:
WallpaperColors systemColors = mColorExtractor
.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
final boolean useDarkTheme = systemColors != null
&& (systemColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
Run Code Online (Sandbox Code Playgroud)
这仅适用于 Android 8.1 ,因为那时主题仅基于壁纸的颜色。在 Android 9.0 上,用户可以在没有任何壁纸连接的情况下进行设置。
根据我在 Android 上看到的内容,这是我所做的:
enum class DarkThemeCheckResult {
DEFAULT_BEFORE_THEMES, LIGHT, DARK, PROBABLY_DARK, PROBABLY_LIGHT, USER_CHOSEN
}
@JvmStatic
fun getIsOsDarkTheme(context: Context): DarkThemeCheckResult {
when {
Build.VERSION.SDK_INT <= Build.VERSION_CODES.O -> return DarkThemeCheckResult.DEFAULT_BEFORE_THEMES
Build.VERSION.SDK_INT <= Build.VERSION_CODES.P -> {
val wallpaperManager = WallpaperManager.getInstance(context)
val wallpaperColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM)
?: return DarkThemeCheckResult.UNKNOWN
val primaryColor = wallpaperColors.primaryColor.toArgb()
val secondaryColor = wallpaperColors.secondaryColor?.toArgb() ?: primaryColor
val tertiaryColor = wallpaperColors.tertiaryColor?.toArgb() ?: secondaryColor
val bitmap = generateBitmapFromColors(primaryColor, secondaryColor, tertiaryColor)
val darkHints = calculateDarkHints(bitmap)
//taken from StatusBar.java , in updateTheme :
val HINT_SUPPORTS_DARK_THEME = 1 shl 1
val useDarkTheme = darkHints and HINT_SUPPORTS_DARK_THEME != 0
if (Build.VERSION.SDK_INT == VERSION_CODES.O_MR1)
return if (useDarkTheme)
DarkThemeCheckResult.UNKNOWN_MAYBE_DARK
else DarkThemeCheckResult.UNKNOWN_MAYBE_LIGHT
return if (useDarkTheme)
DarkThemeCheckResult.MOST_PROBABLY_DARK
else DarkThemeCheckResult.MOST_PROBABLY_LIGHT
}
else -> {
return when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> DarkThemeCheckResult.DARK
Configuration.UI_MODE_NIGHT_NO -> DarkThemeCheckResult.LIGHT
else -> DarkThemeCheckResult.MOST_PROBABLY_LIGHT
}
}
}
}
fun generateBitmapFromColors(@ColorInt primaryColor: Int, @ColorInt secondaryColor: Int, @ColorInt tertiaryColor: Int): Bitmap {
val colors = intArrayOf(primaryColor, secondaryColor, tertiaryColor)
val imageSize = 6
val bitmap = Bitmap.createBitmap(imageSize, 1, Bitmap.Config.ARGB_8888)
for (i in 0 until imageSize / 2)
bitmap.setPixel(i, 0, colors[0])
for (i in imageSize / 2 until imageSize / 2 + imageSize / 3)
bitmap.setPixel(i, 0, colors[1])
for (i in imageSize / 2 + imageSize / 3 until imageSize)
bitmap.setPixel(i, 0, colors[2])
return bitmap
}
Run Code Online (Sandbox Code Playgroud)
我已经设置了各种可能的值,因为在大多数情况下,没有任何保证。
Google刚刚在I / O 2019末尾在此处发布了有关黑暗主题的文档。
为了管理深色主题,必须首先使用Material Components库的最新版本:"com.google.android.material:material:1.1.0-alpha06"。
根据系统主题更改应用程序主题
为了使应用程序根据系统切换到深色主题,只需要一个主题。为此,主题必须具有Theme.MaterialComponents.DayNight作为父级。
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
...
</style>
Run Code Online (Sandbox Code Playgroud)
确定当前系统主题
要了解系统当前是否处于黑暗主题中,可以实现以下代码:
switch (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
case Configuration.UI_MODE_NIGHT_YES:
…
break;
case Configuration.UI_MODE_NIGHT_NO:
…
break;
}
Run Code Online (Sandbox Code Playgroud)
收到主题更改的通知
我认为不可能在主题更改时实现回调通知,但这不是问题。实际上,当系统更改主题时,将自动重新创建活动。这样,在活动开始时放置先前的代码就足够了。
它可从哪个版本的Android SDK运行?
我无法在Android SDK版本28的Android Pie上使用它。因此,我认为这仅适用于SDK的下一版本,该版本将与Q版本29一起启动。
结果
我认为谷歌在 Android Q 中应用深色和浅色主题是基于电池级别的。
\n\n也许是日夜主题?
\n\n\n\n然后,您需要在应用程序中启用该功能。您可以通过调用 AppCompatDelegate.setDefaultNightMode() 来实现此目的,该方法采用以下值之一:
\n\n\n
\n- MODE_NIGHT_NO。始终使用白天(浅色)主题。
\n- MODE_NIGHT_YES。始终使用夜间(黑暗)主题。
\n- MODE_NIGHT_FOLLOW_SYSTEM(默认)。此设置遵循 system\xe2\x80\x99s 设置,该设置在 Android Pie 及更高版本上是系统设置\n(更多信息见下文)。
\n- 模式_夜间_自动_电池。当设备启用 \xe2\x80\x98Battery Saver\xe2\x80\x99 功能时变为暗,否则亮。\xe2\x9c\xa8v1.1.0-alpha03 中的新功能。
\n- MODE_NIGHT_AUTO_TIME 和 MODE_NIGHT_AUTO。根据一天中的时间,白天/夜晚之间发生变化。
\n
我想添加 Vitor Hugo Schwaab 的答案,您可以进一步分解代码并使用isNightModeActive.
resources.configuration.isNightModeActive
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2009 次 |
| 最近记录: |