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,如
应使用离资源 (Resource) 最近的 Context:
5.6 误用
切勿使用 Application Context 加载可使用的资源
Application Context 不保留任何主题背景相关信息,您在 manifest 中设置的主题背景仅用作未明确设置主题背景的 Activity 的默认选择
5.7 强调
6.总结
本文主要讲述了 Android 样式系统的知识体系,介绍如何使用主题背景和主题背景属性来实现对资源的引用,可帮助实现应用的多主题开发支持。掌握这个知识点,有利于我们开发高质量的软件。祝大家工作顺利。
参考链接: Android 样式系统 | 主题背景覆盖.
版权声明: 本文为 InfoQ 作者【Changing Lin】的原创文章。
原文链接:【http://xie.infoq.cn/article/8f1d84dca760c09bb7f2a8e42】。文章转载请联系作者。
评论