【译】Android Styling 3: 使用主题和主题属性的优势

2020/6/20 23:26:24

本文主要是介绍【译】Android Styling 3: 使用主题和主题属性的优势,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

原文:Android Styling: Prefer Theme Attributes
作者:Nick Butcher
译者:Fly_with24


题图来自 Virginia Poltrack


Android Styling 系列的前几篇文章中,我们研究了主题和样式之间的区别,以及使用主题和常用的主题属性的优势

这使我们创建更少地布局和样式,隔离主题内的变化。在实践中,您应 始终* (此处有星号,后文解释) 通过主题属性来控制颜色

Always refer to colors via theme attributes*

传统做法是这样的

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<View …
  android:background="@color/white"/>
复制代码

事实上,您应该引用主题属性,它允许您通过主题来控制颜色,例如,在暗黑主题下提供不同的颜色

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<View …
  android:background="?attr/colorSurface"/>
复制代码

即使您当前不支持其他主题(什么?没有暗黑主题?),我还是建议您采用这种方法,因为这样会使采用主题更加容易

Qualified Color?

您可以在不同的配置下使用不同的色值(例如,@color/foores/values/colors.xmlres/values-night/colors.xml 下均有定义),但我建议您使用主题属性

颜色层级的变化是您必须给颜色一个语义明确的名字,例如您可能不会命名一个颜色为 @color/white 并在暗黑主题内提供一个变体(这会很奇怪并且混乱)。取而代之的是您可能会使用一个语义明确的名字,例如 @color/background。但这样做的问题是它既代表了语义又代表了色值,它没有展示出使用有能够跟随主题变化的能力

使用 @colors 会导致你创建出更多的颜色。如果您在某些场景下需要一个新的语义值,但该色值之前却定义过(例如,你需要一个和 background 相同色值的颜色,但是会将其命名为其他名字),您需要在 colors 文件中再创建一条

通过使用主题属性,我们将色值与颜色的语义名字分离,使调用更加清晰(使用 ?attr/ 语句调用),颜色将随主题而变化。将颜色声明保持为字面值,使您定义了一个「调色板」,您可以在主题层级上进行更改,从而使 color 文件较小且更易维护

Define a palette of colors used by your app and vary them at the theme level

定义 app 的调色板,并在主题层级进行更改

这种方法的另一个好处是,引用这些颜色的 layouts/styles 变得可复用。 由于主题可以覆盖或变化,因此间接表示您无需创建其他布局或样式就可以仅更改某些颜色——您可以将相同的布局用于不同的主题

Always?

前文的 「始终* 通过主题属性来控制颜色」 中的(always)带有星号,因为在某些情况下,您很明确不想按主题更改颜色。例如 Material Design guidelines 中指出有些场景您可能希望在浅色和深色主题使用相同的「品牌色」

在这种特殊场景下,直接引用颜色资源也是可以的

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<FloatingActionButton …
  app:backgroundTint="@color/owl_pink_500"/>
复制代码

State of the art

不使用主题属性的另一种情况是使用 ColorStateList

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<View …
  android:background="@color/primary_20"/>  
复制代码

如果 primary_20 是一个 ColorStateList 并且它本身通过主题属性引用色值,则这可能是有效的(请参见下文)。 虽然通常用于在不同状态(按下,禁用等)下提供不同的颜色,但 ColorStateLists 具有另一种可用于主题化的功能。 它可以帮你为一个颜色设置透明度

<!-- Copyright 2019 Google LLC.	
   SPDX-License-Identifier: Apache-2.0 -->
<selector …
  <item android:alpha="0.20" android:color="?attr/colorPrimary" />
</selector>
复制代码

这种单项 ColorStateList(即,仅提供一种默认颜色,所有状态都一样)有助于减少需要维护的颜色资源数量。它不是通过手动的创建一个新的颜色资源来为 app 的主色设置透明度(每个配置),取而代之的是通过当前主题 colorPrimary 来处理。如果您的 主色 发生了变化,则只需要在一个地方进行更新,而无需跟踪对其进行了调整的所有实例

尽管有用,但要注意此技术的一些注意事项

  1. 如果指定的颜色也具有透明度,则会将 alpha 进行组合,例如 50% 的透明度应用与 50% 透明的白色会得到 25% 的白色

出于此原因,最好将主题颜色指定为完全不透明,并使用 ColorStateLists 修改其 Alpha

  1. alpha 组件是 API 23 后引入的,因此您的 app min sdk 版本比这个低,请确保使用兼容的 AppCompatResources.getColorStateList 并一直使用 android:alpha 命名空间,不要使用 app:alpha 命名空间

  2. 将普通的颜色作为 drawable

View 的 background 属性 需要一个 drawable,我们使用普通的颜色设置 background 是可以的,其内部会把 color 转换为 ColorDrawable,然而 ColorStateList 是无法转换为 Drawable 的(直到 API 29 ColorStateListDrawable 的出现解决了这一问题)。我们可以曲线救国解决此限制。

Enforcement

因此,您应该使用主题属性和 ColorStateList,但是如何在整个代码库或团队中实施呢? 您可以在 code review 时关注,但这并不是个好办法。 更好的方法是依靠工具来解决此问题。这篇文章介绍了通过 lint 检查对不符合规范的用法给出更好的建议。文章在这

Be Indirect

使用主题属性和 ColorStateList 可以将颜色与主题分离,可以使布局和样式更加灵活,方便复用用并保持代码库精简和可维护性

感谢 Florina Muntenescu 和 Chris Banes

译文完

关于我

我是 Flywith24

  • 掘金

  • 简书

  • Github



这篇关于【译】Android Styling 3: 使用主题和主题属性的优势的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程