在仅撰写应用程序中实现全深色主题的正确方法

Proper way of implementing full dark theme in Compose-only applications

提问人:l'hiverviendra 提问时间:8/26/2023 更新时间:11/22/2023 访问量:75

问:

我有一个仅限 Compose 的应用程序,它为用户提供了三个主题选项:

  • 系统
  • 黑暗

通过将参数传递给我的应用的主题函数,在 Activity 的方法中更改主题。onCreate()darkThemeComposable

如果选择并且Android系统支持(Android 10+),则一切正常。SystemDark mode

但是,如果选择此选项,则应用“撰写”中定义的深色主题,底部的系统导航栏将保持白色。Dark

然后我转到文件,它看起来像这样:res/values/themes.xml

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

  <style name="Theme.ExampleApp" parent="android:Theme.Material.Light.NoActionBar" />
</resources>

因此,我假设系统导航栏保持白色,因为在 Compose 中,默认主题是,我们无法通过 Compose 代码控制其颜色。android:Theme.Material.Light.NoActionBar

对于Android 10 +设备来说,这不是一个大问题,因为它们可以简单地选择选项,然后从Android中手动打开/关闭系统。SystemDark mode

但是对于不支持该系统的设备,它们的导航栏保持白色,这看起来很糟糕。Dark mode

因此,我做了一些搜索,并找到了一种“修复”此问题的方法(主要来自本文)。

  1. 首先,我将文件中的父主题更改为以下内容:styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>

  <style name="Theme.ExampleApp" parent="Theme.AppCompat.DayNight" />
</resources>
  1. 除非您的活动扩展,否则这不起作用。默认的仅撰写应用程序具有其活动扩展 。所以:AppCompatActivityComponentActivity
class MainActivity : AppCompatActivity()
  1. 然后我使用以下功能切换到所谓的“夜间模式”:
// For SDK <= 30
AppCompatDelegate.setDefaultNightMode()

// For SDK >= 31
uiManager.setApplicationNightMode()

它有效!

但是,我对这种方法有一些担忧和疑问。

  1. 是否可以将样式用于仅撰写应用程序?它看起来很旧,我想知道它是否破坏了 Compose 中的某些东西。Theme.AppCompat.DayNight

  2. 在仅撰写应用程序中使用而不是使用有什么缺点?我不使用 s,所以我真的不需要它,但也许它再次破坏了 Compose 中的某些东西?它会增加 .apk 大小吗?AppCompatActivityComponentActivityFragment

  3. 我不知道调用哪些参数来调用函数和“遵循系统主题”模式。对于第一个函数,有 ,但第二个函数没有它,只有 和 。他们都说他们根据当前时间切换到“夜间模式”,我真的不想要。对于 Android 10+,我不希望它们破坏其原生功能。setDefaultNightMode()setApplicationNightMode()MODE_NIGHT_FOLLOW_SYSTEMMODE_NIGHT_AUTOMODE_NIGHT_CUSTOMDark mode

安卓 android-jetpack-compose android-appcompat android-dark-theme

评论


答:

0赞 AndrazP 11/22/2023 #1

如果系统状态或导航栏未随应用内设置主题而更改,请确保:

  1. 删除 和 from 等属性。android:windowLightStatusBarandroid:windowLightNavigationBarthemes.xml
  2. 在撰写主题背景中设置并打开。isAppearanceLightStatusBarsisAppearanceLightNavigationBarsWindowInsetsControllerCompat
@Composable
fun AppTheme(
   useDarkTheme: Boolean =  isSystemInDarkTheme(),
   content: @Composable () -> Unit
) {
 
 // color scheme selection code

 // Add primary status bar color from chosen color scheme.
 val view = LocalView.current
 if (!view.isInEditMode) {
    SideEffect {
        val window = (view.context as Activity).window
        window.statusBarColor = colors.primary.toArgb()
        WindowCompat.getInsetsController(window, view).apply {
            isAppearanceLightStatusBars = !isDarkTheme
            isAppearanceLightNavigationBars = !isDarkTheme
        }
    }
 }
   
 MaterialTheme(
   colorScheme = colors,
    content = content
 )
}