如何在安卓系统中强制启用深色主题?

10
根据文档,我只需要在我的活动清单中设置android:forceDarkAllowed=true并继承主题parent="Theme.MaterialComponents.DayNight"。 我试过了,但它没有起作用。

这是我的清单文件:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:forceDarkAllowed="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

这是我的styles.xml样式:

<style name="AppTheme" parent="Theme.MaterialComponents.Light">
    ...
</style>

<style name="AppTheme.Dark" parent="Theme.MaterialComponents.DayNight">
    ...
</style>

我试图通过以下代码获取活动主题名称:

resources.getResourceName(
    packageManager.getPackageInfo(packageName, PackageManager.GET_META_DATA)
        .applicationInfo.theme
)

它显示给我com.example.name:style/AppTheme而不是AppTheme.Dark。我该如何让MainActivity在运行应用程序时自动将自身设置为使用AppTheme.Dark(即暗模式),使用android:forceDarkAllowed

3个回答

17
这不是Android 10上深色模式的工作方式。
首先,无论用户是否启用深色模式,Android都不会在任何时候神奇地将.Dark附加到您的主题中。您有android:theme="@style/AppTheme"。因此,Android始终使用AppTheme,而不会使用AppTheme.Dark
其次,DayNight的想法是您始终将其用作基础主题,Android将根据用户请求在正常和深色模式之间切换。因此,如果您将AppTheme切换为扩展DayNight,并且删除AppTheme.Dark,则可以匹配文档所述内容。 android:forceDarkAllowed用于在无法使用DayNight主题的情况下,您希望Android尝试自动将UI转换为深色主题的情况。如果您想保持AppTheme扩展Light而不是DayNight,则可能有效(我个人没有尝试过使用MaterialComponents主题)。但即使如此,它也只会在用户启用深色模式(例如,点击通知栏磁贴)时才生效。
例如,在这个示例应用程序中,我使用DayNight作为我的主题:
<resources>

  <!-- Base application theme. -->
  <style name="AppTheme" parent="Theme.AppCompat.DayNight">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
  </style>

</resources>

res/values/res/values-night/中,我对这些颜色有不同的定义。我没有使用forceDarkAllowed。当用户切换到夜间模式时,我的UI会从以下状态转换:

DayNight normal

to:

DayNight dark mode

当我运行应用程序时,如何使MainActivity自动设置为使用AppTheme.Dark(即深色模式),并使用android:forceDarkAllowed?
你不需要这样做。
如果你想一直使用深色主题,请使用普通主题(不是Light,也不是DayNight)。

谢谢!我很喜欢你非常详细的解释。我知道我可以通过编程和用户请求来更改为暗色主题。然而,我对android:forceDarkAllowed部分感到非常困惑。我会再次尝试重新阅读它,看看是否有遗漏的内容。真的非常感谢你,这太完美了。 - Richard
2
@Richard:android:forceDarkAllowed 主要是为了现有的应用程序,想要尝试在不重新设计其主题和用户界面的情况下添加深色模式支持。它的效果出奇的好,但仍然会犯错误。您需要彻底测试您的应用程序,以确认自动转换不会使一些内容变得丑陋或无法使用。 - CommonsWare
啊,我明白了。我在样式Theme.AppCompatTheme.MaterialComponents上测试了android:forceDarkAllowed,它确实像你所说的那样工作。它神奇地将颜色转换为暗色主题模式。然后,我在Theme.AppCompat.DayNight/LightTheme.MaterialComponents.Light/DayNight上再次尝试,但却没有起作用。 - Richard
我读到这行代码 首先,Android 不会在任何时候自动将 .Dark 添加到你的主题中,立刻得出结论,这个答案来自于 CommonsWare。 - Bugs Happen
有没有办法自定义“forceDarkAllowed”的色调? - Pavel Poley
@PavelPoley: 我不知道有任何的选项可以做到那个,但是我没有研究过那个点。 - CommonsWare

7
  1. 如果您的应用程序使用深色主题(例如Theme.Material),则不会应用强制暗黑模式。同样,如果您的应用程序主题继承自DayNight主题,则由于自动主题切换,不会应用强制暗黑模式。
  2. 暗黑主题在Android 10(API级别29)及更高版本中可用。请确保您的设备API级别为29+,并且gradle中的目标SDK为29。
  3. 有两种方法可以应用暗黑主题:
    1. DayNight-可定制主题-您可以控制深色/浅色主题的外观。
    2. Force dark-您可以控制浅色主题,并且如果用户选择暗黑模式,则系统将在运行时将您的视图转换为暗黑主题。

5
有设置可以动态设置白天或黑夜,而不受当前系统设置的影响。

Each of the options map directly to one of the AppCompat.DayNight modes:

Light - MODE_NIGHT_NO
Dark - MODE_NIGHT_YES
System default - MODE_NIGHT_FOLLOW_SYSTEM

To switch the theme, call AppCompatDelegate.setDefaultNightMode().

https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#change-themes

这适用于设置日夜主题。如果您想利用Android 10中的Force Dark,它适用于.Light子主题。它不会应用于任何DayNight或固有的暗色主题。
应用程序必须通过在活动主题中设置android:forceDarkAllowed="true"来选择Force Dark。此属性设置在所有系统和AndroidX提供的浅色主题上,例如Theme.Material.Light。

https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#force-dark

以下是文档还指定了如何排除某些资源或代码。
Force Dark 可以通过 android:forceDarkAllowed 布局属性或 setForceDarkAllowed() 在特定视图上进行控制。
此外,还有一些方法可以检测当前系统的明亮/暗淡设置并使用上述选项做出响应,但这是另一篇文章的内容。
这不是一个很好的黑暗主题解决方案,我为与被接受的答案重叠而道歉,但我不同意声称某些事情不可能,因为它不被 preferred。

2
这是一个非常好的、被低估的回答! - LordScone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接