什么时候应该使用 Theme.AppCompat 与 ThemeOverlay.AppCompat?

Posted

技术标签:

【中文标题】什么时候应该使用 Theme.AppCompat 与 ThemeOverlay.AppCompat?【英文标题】:When should one use Theme.AppCompat vs ThemeOverlay.AppCompat? 【发布时间】:2015-01-30 01:13:36 【问题描述】:

有以下 Theme.AppCompat 类:

Theme.AppCompat
Theme.AppCompat.Light
Theme.AppCompat.Light.DarkActionBar
Theme.AppCompat.NoActionBar
Theme.AppCompat.Light.NoActionBar
Theme.AppCompat.DialogWhenLarge
Theme.AppCompat.Light.DialogWhenLarge
Theme.AppCompat.Dialog
Theme.AppCompat.Light.Dialog
Theme.AppCompat.CompactMenu

以及以下 ThemeOverlay.AppCompat 类:

ThemeOverlay.AppCompat
ThemeOverlay.AppCompat.Light
ThemeOverlay.AppCompat.Dark
ThemeOverlay.AppCompat.ActionBar
ThemeOverlay.AppCompat.Dark.ActionBar

例如,为什么要使用 ThemeOverlay.AppCompat.light 与 Theme.AppCompat.Light?我看到为 ThemeOverlay 定义的属性要少得多——我很好奇 ThemeOverlay 的预期用例是什么。

【问题讨论】:

【参考方案1】:

Theme.AppCompat 用于为整个应用设置全局主题。 ThemeOverlay.AppCompat 用于覆盖(或“覆盖”)特定视图的主题,尤其是工具栏。

让我们看一个例子来说明为什么这是必要的。

带有 ActionBar 的应用主题

ActionBar 通常显示在应用程序中。我可以通过设置colorPrimary 值来选择它的颜色。但是,更改主题会更改 ActionBar 上文本的颜色。

<style name="AppTheme" parent="Theme.AppCompat">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

由于我的原色是深蓝色,我可能应该在操作栏中使用浅色文本颜色的主题之一,因为黑色文本很难阅读。

隐藏 ActionBar 并使用工具栏

使用 Theme.AppCompat 而不是 Theme.Material 的全部意义在于,我们可以允许旧版本的 android 使用我们的 Material Design 主题。问题是旧版本的 Android 不支持 ActionBar。因此,documentation 建议隐藏 ActionBar 并将 Toolbar 添加到您的布局中。要隐藏 ActionBar,我们必须使用 NoActionBar 主题之一。下图显示了隐藏 ActionBar 的工具栏。

但是,如果我想要带有 DarkActionBar 的 Light 主题怎么办?因为我必须使用 NoActionBar,所以这不是一个选项。

覆盖应用主题

这就是 ThemeOverlay 的用武之地。我可以在我的 Toolbar xml 布局中指定 Dark ActionBar 主题。

<android.support.v7.widget.Toolbar
    ...
    android:background="?attr/colorPrimary"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

这最终可以让我们得到我们想要的效果。 Dark.ActionBar 主题覆盖此特定场合的 Light 应用主题。

应用主题:Theme.AppCompat.Light.NoActionBar 工具栏主题:ThemeOverlay.AppCompat.Dark.ActionBar

如果您希望弹出菜单更轻,可以添加:

app:popupTheme="@style/ThemeOverlay.AppCompat.Light"

进一步研究

我通过实验和阅读以下文章了解到这一点。

Setting Up the App Bar Use android:theme and ThemeOverlay to theme specific Views and their descendents Theming with AppCompat Use colorPrimary to colorize your App Bar Theme vs Style

【讨论】:

使用Themeoverlay时如何让状态栏透明? 我想知道如何使用新的 MaterialToolbar 来实现这一点 @David,我现在主要使用 Flutter,所以我没有跟上新的 Android 开发。如果您找到答案,请随时返回此处发表评论、编辑我的答案或添加您自己的答案。【参考方案2】:

根据 AppCompat 的创建者Theme vs Style blog post:

[ThemeOverlays] 是覆盖普通 Theme.Material 主题的特殊主题,覆盖相关属性以使它们变亮/变暗。

ThemeOverlay + ActionBar

目光敏锐的你也会看到 ActionBar ThemeOverlay 衍生产品:

ThemeOverlay.Material.Light.ActionBar ThemeOverlay.Material.Dark.ActionBar

这些只能通过新的actionBarTheme 属性与操作栏一起使用,或者直接在您的工具栏上设置。

这些目前与父母不同的唯一事情是他们将colorControlNormal 更改为android:textColorPrimary,从而使任何文本和图标不透明。

【讨论】:

嗨,Ian,我从 Android 1 的 Beta 时代就开始为 Android 开发,但我真的从来没有完全理解过主题。它总是跟踪和错误。您、Chet 或 UI Toolkit 团队的任何其他人是否就此进行了很好的讨论?如果不是,那可能是下一个 I/O 的好主意。

以上是关于什么时候应该使用 Theme.AppCompat 与 ThemeOverlay.AppCompat?的主要内容,如果未能解决你的问题,请参考以下文章

弹出AlertDialog的时候报You need to use a Theme.AppCompat theme (or descendant) with this activity错误

Theme.AppCompat无全屏主题解决办法

如何使用主题和 Theme.AppCompat.DayNight 更改操作栏中的文本颜色

Android : Theme.Holo VS Theme.AppCompat

ActionBarCompat: java.lang.IllegalStateException: 你需要使用 Theme.AppCompat

Theme.AppCompat.Light.NoActionBar AdjustResize 不起作用