写点什么

Android Styling System

用户头像
Changing Lin
关注
发布于: 2021 年 01 月 27 日
Android Styling System

1. 背景

本文主要对安卓样式系统进行分析,包括主题背景和样式两大主题,希望可以形成知识体系,并且应用到日常开发过程中,让布局和样式更加灵活,提高代码复用性并保持代码库的精简和易维护性。


2. 主题背景与样式的区别

2.1 主题背景 != 样式

2.1.1 共同点

  • 使用相同的<style>语法

  • 使用键值对 (Key-Value) 来存储数据,==键 (Key) 代表属性,值 (Values) 代表资源==

2.1.2 不同点

  • 服务的目的截然不同 / 针对的==对象或应用场景==不同

2.2 样式

2.2.1 样式里面有什么

  • 样式是==View 属性 (View Attributes) 值的集合==

  • 一个样式对应一种类型的 Widget

  • 可以在多个 View 中复用同一个样式,而且还容易维护

2.2.2 使用方法

  • 一个 View 只能使用一个样式

2.2.3 范围

  • 样式只有在使用它的 View 上才起作用,子 View 不起作用

2.3 主题背景

2.3.1 什么是主题背景?

  • 一组命名的资源的集合

  • 可以被样式或者布局文件等引用

  • 由 Map<theme attribute, resource> 结构组成

  • 类似于接口 (Interface)

  • 主题背景属性:==一种对 Android 资源的语义名称 (Sematic name);对一个值的命名,为这些标有名字的资源提供了具体的值==

2.3.2 使用方法

  • 可以把一个主题背景设置给一个组件(Application/Activity/View/ViewGroup)

  • 可以使用 ContextThemeWrapper 类把一个主题背景设置到已经存在的 Context 上,也可使用 inflate 方法创建布局

  • 可以通过引用主题背景属性来创建灵活的 Widget

  • 通过使用 ?attr/themeAttributeName 语法获得此主题背景中的语义属性代表的值

2.3.3 范围

  • 任何一个带有 Context (如 Activity, View or ViewGroup) 的对象 (Object) 都可以通过访问 Context 的属性来访问主题背景

  • 以树的形式组织而成,把主题背景设置到一个树状结构的任意一层,此层及下一层都会受到影响,这种功能仅在初始化布局的时候生效

  • 在初始化布局之前:==调用 Context 提供的 setTheme 方法;主题背景提供的 applyStyle 方法==

  • ==布局初始化完毕之后==,再调用 setTheme 或者 applyStyle 方法,==不会生效==

3.常见的主题背景属性

3.1 还可以使用哪些主题背景属性的功能呢?

  • 颜色

  • 大小

  • Drawables

  • TextAppearance

  • 形状

  • 按钮风格

  • Floats

3.2 命名空间

  • 由 Android 平台定义的,需要使用 android 命名空间来引用由它们自己定义的属性 (类似于布局中使用 View 属性 android:id)

  • 编译到您的应用但不是来自于静态库的属性 (AppCompact 或者 MDC) ,==使用它们时不需要命名空间 (类似于布局中使用 app:baz)==

  • 平台跟库有时候定义了相同的属性,优先使用非平台版本的属性,它们可以被所有级别的 API 使用

3.3 如何自定义一个主题背景

3.3.1 在 attrs.xml 中定义主题背景属性:

3.3.2 在不同的主题背景中使用不同的值:

3.3.3 给两个界面使用的布局文件中使用主题背景属性:

4.主题背景属性

创建更少的布局或样式,以隔离主题背景中的修改

4.1 合格的 Colors 文件

  • 通过使用主题背景属性,我们可以将语义颜色的声明从提供它们的值中区分开来

  • 让使用方更清楚地了解到颜色会随主题背景而变化 (因为它们使用 ?attr/ 语法)

  • 将颜色声明保持为字面值,您就可以自定义应用使用的颜色调色板,并在主题背景级别修改它们

  • 您不需要创建其他布局或样式就可以更改某些颜色,您可以在相同的布局中使用不同的主题背景

4.2 始终使用?

  • 直接引用颜色资源

4.3 当前发展状况

4.3.1 使用 ColorStateLists 实现主题化功能的方法?

  • 可在选取的颜色上指定透明度值

  • 这种单项 ColorStateList (即只提供单个默认颜色,而非每种状态的不同颜色),有助于减少您需要维护的颜色资源数量

4.3.2 注意事项

  • 如果指定的颜色也具有 alpha 值,则 alpha 会被合并。

  • 仅在 API 23 中添加了 alpha 组件,请确保使用支持此行为的 AppCompatResources.getColorStateList;并始终使用 android:alpha 命名空间,而绝不使用 app:alpha 命名空间

  • 通常,我们使用简写法,将颜色设置为 Drawable,

  • View 的背景是一个 Drawable,此简写把给定的颜色强转成了一个 ColorDrawable;但没有办法把 ColorStateList 转换成 Drawable (API 29 之前使用 olorStateListDrawable 解决这个问题;但有另外一种方法:请确保您的 backgroundTint 支持您的 View 所需的状态,例如,如果被禁用时需要更改。

4.4 间接使用

使用主题背景属性和 ColorStateList 将颜色分解为主题背景的方法,可使您的布局和样式更加灵活,提高代码复用性并保持代码库的精简和易维护性。

5.主题背景覆盖

5.1 范围

  • 在树结构中的任何层级上设置主题背景,都不会替换当前生效的主题背景,但会将其覆盖 (Overlay)

5.2 过度重叠

  • 主题背景覆盖 (Theme Overlay)

  • 主题背景覆盖是限定范围的主题背景,定义的属性要越少越好,它的作用只是为了覆盖另外一个主题背景

  • 主题背景覆盖通常 (但并不总是) 是没有父级的

  • 可以认为在应用中可以使用两种 "类型" 主题:1."完整" 主题背景;2.主题背景覆盖

5.3 永远存在

  • 总会有一个有效的主题背景,即使您未在应用中的任何地方指定一个主题背景,您也会继承==默认主题==

  • 绝对不应该在 View 中使用一个 "完整" 的主题背景,而应使用主题背景覆盖

5.4 成本效益

  • 每次您声明 android:theme 时,您都在创建一个新的 ContextThemeWrapper,它会分配新的主题背景 (Theme) 和资源 (Resources) 实例

  • 它还需要解决==多层级样式化的间接引用问题==

  • 注意==不要过度使用主题==,您应该监控它们的影响,特别是在重复使用的情况下,例如: ==RecyclerView 项的布局或者配置文件==

5.5 在上下文中使用

  • 如果您在代码中使用 Context 来获取资源 (Resource),请确保您使用的是正确的 Context,如

someView.background = AppCompatResources.getDrawable(requireContext(), R.drawable.foo)
复制代码
  • 应使用离资源 (Resource) 最近的 Context:

someView.background = AppCompatResources.getDrawable(someView.context, R.drawable.foo)
复制代码

5.6 误用

  • 切勿使用 Application Context 加载可使用的资源

  • Application Context 不保留任何主题背景相关信息,您在 manifest 中设置的主题背景仅用作未明确设置主题背景的 Activity 的默认选择

5.7 强调

6.总结

本文主要讲述了 Android 样式系统的知识体系,介绍如何使用主题背景和主题背景属性来实现对资源的引用,可帮助实现应用的多主题开发支持。掌握这个知识点,有利于我们开发高质量的软件。祝大家工作顺利。


参考链接: Android 样式系统 | 主题背景覆盖.


发布于: 2021 年 01 月 27 日阅读数: 14
用户头像

Changing Lin

关注

获得机遇的手段远超于固有常规之上~ 2020.04.29 加入

我能做的,就是调整好自己的精神状态,以最佳的面貌去面对那些未曾经历过得事情,对生活充满热情和希望。

评论

发布
暂无评论
Android Styling System