在 Android 样式系统系列的前几篇文章中,我们介绍了主题背景与样式的区别,以及为什么说通过主题背景和公共主题背景属性来分解您要实现的内容是一个不错的主意,请点击链接回顾:

  • Android 样式系统 | 主题背景和样式

  • Android 样式系统 | 常见的主题背景属性

这会让我们通过创建更少的布局或样式,以隔离主题背景中的修改。在实际开发中,您通常希望根据主题背景改变颜色,因此您应该始终通过主题背景属性来引用颜色。这意味着您可以将如下代码视为有代码异味 (Code smell):

<View …  android:background="@color/white"/>

相反,您应该使用主题背景属性,它允许您按主题更改颜色,例如,在深色主题中提供一个不同的值:

<View …  android:background="?attr/colorSurface"/>
  • 深色主题https://developer.android.google.cn/guide/topics/ui/look-and-feel/darktheme

即使您当前不支持其他主题 (什么,您的应用还没有支持深色主题?),我们依然建议您采用这种方法,因为这样会让新主题的采用变得更加简单。

合格的 Colors 文件

您可以通过在不同的配置中添加不同的值来改变颜色 (例如,在 res/values/colors.xml 中和在 res/values-night/colors.xml 中的备选值里均定义 @color/foo),但我们依然建议您使用主题背景属性来替代它们。对颜色层级的区分,会迫使您给颜色赋予语义化名称,换句话说,您应该不会在给颜色命名为 @color/white 的同时,又为深色模式提供一个深色变体,这会让人感到非常困惑。所以,您可能会想要使用一个语义化名称,例如 @color/background。这种方法带来的问题是它合并了颜色声明和具体的值,因此,它并没有指出颜色是可以或者能够随主题背景而变化的。@colors 的变化也会鼓励您创造更多颜色。如果在不同的情境下要使用具有相同值的、新的语义化命名的颜色 (即,不是背景色但应该使用相同颜色),这时候您仍需要在 colors 文件中创建新的条目。通过使用主题背景属性,我们可以将语义颜色的声明从提供它们的值中区分开来,而且让使用方更清楚地了解到颜色会随主题背景而变化 (因为它们使用 ?attr/ 语法)。将颜色声明保持为字面值,您就可以自定义应用使用的颜色调色板,并在主题背景级别修改它们,这会让 color.xml 较小且易维护。这种方法的额外好处是,布局/样式引用这些颜色时复用性变得更高。由于主题背景可以被覆盖或者改变,因此这间接表示: 您不需要创建其他布局或样式就可以更改某些颜色——您可以在相同的布局中使用不同的主题背景。

始终使用?

在某些情况下,您或许不想按照主题背景更改颜色。例如,在 Material Design 规范文档中提到,您可能希望在浅色和深色主题中均使用同一类型的颜色。

  • Material Design 规范文档https://material.io/design/color/dark-theme.html#ui-application

在这种特殊情况下,直接引用颜色资源是再合适不过的:

<FloatingActionButton …  app:backgroundTint="@color/owl_pink_500"/>

当前发展状况

当使用 ColorStateLists时,您可能也不会在您的布局/样式中直接引用主题背景属性。

<View …  android:background="@color/primary_20"/>
  • ColorStateListshttps://developer.android.google.cn/reference/android/content/res/ColorStateList

如果 primary_20 是一个 ColorStateList,它本身引用主题背景属性来获取色值也可能是合理的 (请参见下文)。ColorStateLists 通常为不同的状态 (按下,禁用等) 提供不同的颜色,但它还有另外一种可用于主题化功能您可在选取的颜色上指定透明度值:

<selector …  <item android:alpha="0.20" android:color="?attr/colorPrimary" />selector>

这种单项 ColorStateList (即只提供单个默认颜色,而非每种状态的不同颜色) 有助于减少您需要维护的颜色资源数量。它并没有定义一个新的颜色资源的方式来手动为您 (每一个配置文件) 的 primary 颜色设置 alpha 值,而是通过改变当前主题背景中的 colorPrimary 的方式。如果您的原始颜色发生了变化,则只需要在一个地方进行更新,无需调整所有已更新的地方。

虽然此技术很有用,但仍有一些注意事项:

1. 如果指定的颜色也具有 alpha 值,则 alpha 会被合并。例如,将 50% 的 alpha 应用于 50% 的不透明白色中,将产生 25% 的白色:

<selector …  <item android:alpha="0.50" android:color="#80ffffff" />selector>

因此,最好将主题背景颜色指定为完全不透明,然后使用 ColorStateLists 修改它们的 alpha。2. 仅在 API 23 中添加了 alpha 组件,因此,如果您的最小 sdk 低于这个版本,请确保使用支持此行为的 AppCompatResources.getColorStateList (并始终使用 android:alpha 命名空间,而绝不使用 app:alpha 命名空间)。

  • AppCompatResources.getColorStateListhttps://developer.android.google.cn/reference/androidx/appcompat/content/res/AppCompatResources.html#getColorStateList(android.content.Context,%20int)

3. 通常,我们使用简写法,将颜色设置为 Drawable,例如:

<View …  android:background="@color/foo"/>

View 的背景是一个 Drawable,此简写把给定的颜色强转成了一个 ColorDrawable。但是没有办法把 ColorStateList 转换成 Drawable (API 29 之前使用 ColorStateListDrawable 解决这个问题)。

  • ColorDrawablehttps://developer.android.google.cn/reference/android/graphics/drawable/ColorDrawable
  • ColorStateListDrawablehttps://developer.android.google.cn/reference/android/graphics/drawable/ColorStateListDrawable

但是,我们可以通过迂回的方式绕过此限制:

<View …  android:background="@drawable/a_solid_white_rectangle_shape_drawable"  app:backgroundTint="@color/some_color_state_list"/>

请确保您的 backgroundTint 支持您的 View 所需的状态,例如,如果被禁用时需要更改。

强制执行

即使您已经说服自己使用主题背景属性和 ColorStateList,但如何在代码库或者团队中使用呢?您可以在 Code review 期间尝试保持警惕,但它的扩展性不是很好。更好的方法是依靠工具来解决此问题。《Making Android Lint Theme Aware》这篇文章简述了如何通过添加 Lint 检查来寻找直接引用颜色的用法,并涵盖了文中提及到的所有建议。

  • 《Making Android Lint Theme Aware》

    https://proandroiddev.com/making-android-lint-theme-aware-6285737b13bc

间接使用

使用主题背景属性和 ColorStateList 将颜色分解为主题背景的方法,可使您的布局和样式更加灵活,提高代码复用性并保持代码库的精简和易维护性。我们将在后续文章中介绍更多主题背景的用法以及它们之间的相互影响,感兴趣的读者请继续关注。


推荐阅读

 点击屏末  | 了解更多与 Android 界面相关的内容和教程


android colorstatelist_Android 样式系统 | 主题背景属性相关推荐

  1. Android 样式系统 | 常见的主题背景属性

    在前一篇 Android 样式系统文章中,我们介绍了主题背景与样式的区别,以及如何编写灵活的样式与布局代码用于抽离可变化部分. 我们建议使用主题背景属性来间接引用资源,您可以在不同的模式下 (比如在深 ...

  2. Android样式和主题背景

    简介: 本文将简单介绍Android样式与主题背景的相关内容 文章目录 前言 一.样式 二.主题背景 三.样式层次结构 四.创建并应用样式 五.自定义默认主题 六.添加特定于版本的样式 七.常见的主题 ...

  3. Android样式和主题背景·

    简介: 本文将简单介绍Android样式与主题背景的相关内容 文章目录 前言 一.样式 二.主题背景 三.样式层次结构 四.创建并应用样式 五.自定义默认主题 六.添加特定于版本的样式 七.常见的主题 ...

  4. Android 用户界面---样式和主题(Styles and Themes)(二)

    样式属性 理解了样式是如何定义的之后,就需要学习<item>元素都定义了那些有效的样式属性类型.你可能已经熟悉了像layout_width和textColor属性,但是还有更多的可以使用的 ...

  5. Android中样式及主题

    Android应用程序中不可避免的需要使用的样式和主题,样式指定一般指定View的高度.字体.字体颜色.背景,Android里的样荐定义在Style.xml文件里.主题也是一种样式,只不过它是应用在整 ...

  6. Android Theme修改系统主题

    1,Theme 的作用范围 [1]Theme(主题)是针对窗体级别的,改变窗体样式,对整个应用或某个Activity存在全局性影响.  [2]主题依然在<style>元素里边申明,也是以同 ...

  7. Android Studio (11)---使用主题背景编辑器设计应用主题背景

    使用主题背景编辑器设计应用主题背景 Android Studio 包含被称为主题背景编辑器的视觉辅助工具,以帮助您: 创建和修改应用的主题背景. 调整不同资源分类器的主题背景. 可视化更改公共 UI ...

  8. android selector下的设置背景属性值

    在res/drawable文件夹新增一个文件,此文件设置了图片的触发状态,你可以设置 state_pressed,state_checked,state_pressed,state_selected, ...

  9. CSS字体样式值,背景属性

    面试题: Html 1,html语义化 2,meta viewport相关 3,canvas 相关 CSS 1,盒模型 1.1,ie盒模型算上border.padding及自身(不算margin),标 ...

最新文章

  1. Windows:让Windows XP中的IIS支持多站点的工具
  2. 新加坡计划通过区块链促进东盟金融包容性
  3. 无招胜有招之Java进阶JVM(九)HotSpot
  4. python面向对象三大特性、类的约束、print带颜色输出及super补充
  5. 病毒 Worm.Logo.g
  6. 利用可编程大容量网盘onedrive配合公有云做你的nas及做站
  7. win10的当前桌面壁纸保存位置
  8. 进程间的通信方式有哪些?
  9. java 假设检验_据说假设检验是个很难的题
  10. python绘制多段数码管
  11. 光线cms,如何增加像百度一样的智能提示
  12. 【WebService】Caused by: org.apache.cxf.transport.http.HTTPException: HTTP respon ...
  13. 单片机:按键调节时钟
  14. docker 命令详解(二十四):push
  15. 百度语音合成 java 教程_调用百度语音合成接口
  16. 信息技术时代杂志信息技术时代杂志社信息技术时代编辑部2022年第9期目录
  17. 机器语言、汇编语言和高级语言的区别和互相间的关系
  18. keil STM32中sct 分散加载文件学习
  19. XILINX DDR4 SDRAM(MIG)笔记2(基于VU9P FPGA)
  20. BZOJ 1064 假面舞会

热门文章

  1. REST / HTTP方法:POST与PUT与PATCH
  2. Java代理初学者指南
  3. JDK 13:什么是AggressiveOpts?
  4. guava的正确引入方式_使用Guava的AbstractInvocationHandler正确完成代理
  5. 使用threadlocal_何时以及如何使用ThreadLocal
  6. 知识蒸馏 循环蒸馏_Java垃圾收集蒸馏
  7. 首选System.lineSeparator()以用Java编写系统相关的行分隔符字符串
  8. drools。drools_Drools Planner重命名为OptaPlanner:宣布www.optaplanner.org
  9. 使用Java将项目插入DynamoDB表
  10. HotSpot的-XshowSettings标志的简单性和价值