Theme的实质也是Style,所以Theme的定义格式与Style的基本一致,具体格式如下(都定义在res目录下,自己随意起名的xml中):
<?xml version="1.0" encoding="utf-8"?>可以看见,一个style在定义时至少需要一个name的属性用来被使用者识别,其中的item就是各种不同的属性与指定的属性值,而style除过有name属性以外还可以有parent属性,在这里你先理解为类似java的继承重写关系即可,后面会详细介绍。
不过这里要特别注意,一般在style中使用parent字段的继承适用于继承系统平台现有定义的style,而我们想要继承自己实现的style一般不会通过parent字段来实现,而是通过指定格式的name字段来实现,如下:
看见name字段了吗?证明这个style继承自我们上面自定义的CodeFont style,可见我们自定义的继承是通过“.”来实现的,在使用时只需要@style/CodeFont.Red即可使用该继承重写的style啦,如果你还想继续在这基础上继承,那写法还是一样的,具体如下:
整明白Theme与Style的这个约定了么!就是这么简单而已,不过要注意这两种的严格区别,别乱用,譬如将系统预定义的通过name来使用时错误的。
接着我们来看看style中item属性是怎么搞来的,这玩意如果我们定义控件的style则可以直接在对应控件或者Window的API文档中或者R.attr
文档中找到支持哪些属性,依次选择合适的进行使用即可(特别提醒,这个技能很重要,譬如有时候你会说我自定义的Dialog为何背景周边多一个黑框啥玩意的问题,然后上网一顿复制别人的style,也不明白别人为啥这么写,其实一个很重要的技巧就是遇到这种问题自己去API查下相关的属性就搞定了。)。使用系统已存在属性时切记不要忘记<item name="android:inputType">
前面的android:前缀,还有就是item中存在的属性不见得对所有View都有效,譬如Theme中需要的以windowXXX开头的属性就不适用于View,但是不会报错,只是View会忽略这些不适合自己的属性,应用适合自己的属性。
2-2 Theme与Style的使用
有了上面的知识我们已经能够定义出Theme与Style了,下来就是怎么将定义的这些样式应用到UI中啦。将style设置到UI主要分两类,如下:
-
对于单个控件通过style进行引入(注意:ViewGroup的style不会向下传递到子View上,除非用theme方式);
-
对于Activity、Application等窗口级向下应用的通过theme进行引入;
在Android中有许多预定义的style供我们使用,所以在使用主题时我们可以如下使用:
#b0b0ff
2-3 Theme的兼容性处理
在新版本的Android中添加了很多新的Theme,而老版本又不兼容这些Theme,所以很多时候我们可能需要处理一下这种兼容性问题,譬如我们在res/values/styles.xml文件中定义如下Theme:
当我们想在Android3.0(API 11)以上使用新的Theme则可以res/values-v11目录下定义如下Theme:
这样当我们编译的APK在不同的设备上运行时就能自己切换选择适合自己平台的Theme了。
2-4 Android系统预制的Theme与Style选择
话说Android应用层开发之所以简单的原因就在于系统已经帮我们实现了很多自由选择的功能,关于Style与Theme也不例外(应用层开发难就难在知识面很广),具体使用可以记住如下秘诀:
-
当我们想要知道Theme具体有哪些属性可以有效使用时,可以查阅API的R.styleable进行选择。
-
当我们想要知道Style具体有哪些属性可以有效使用时,可以查阅API的R.attr进行选择。
-
系统为我们提供了很多实用的Theme与Style,我们还可以通过查阅API的R.style进行选择(要注意的是这里的文档查到的不一定全,最好的办法是去查FW下base的res或者appcompat的res),不过要注意,在API中譬如Theme_NoTitleBar主题样式在我们xml引用时要替换为@android:style/Theme.NoTitleBar的格式。
2-5 Android应用资源拓展语法
上面提到的都是Theme与Style相关的东西,其实这两个东西实质都属于res资源的处理,关于Android的res资源使用规则和不同平台软硬件系统匹配的策略不属于本文范围,不过也很简单,感兴趣的同学可以移步到API Guide的App Resources进行研读。这里我们主要简单说下资源的引用语法,因为Theme与Style中也会经常使用到,免得带来不必要的疑惑。
Android中资源在Java文件中引用的语法定义如下:
[<package_name>.]R.<resource_type>.<resource_name>
//注意:当资源在当前APP中则package_name可以省略,当为系统的资源则可换位譬如android.
Android中资源在XML文件中引用的语法定义如下:
@[<package_name>:]<resource_type>/<resource_name>
//注意:package_name的规则同上java中,不过在XML中引入不是本包资源时要注意格式,譬如引用系统的资源格式为android:textColor=“@android:color/secondary_text_dark”
Android系统预制资源在XML文件中引用的特殊语法定义如下:
//可以引用系统所有资源,public & private
@*android:type/name
//只能引用系统public的资源
@android:type/name
//注意:没在frameworks/base/core/res/res/values/public.xml(也就是<sdk_path>\platforms\android-X\data\res\values\public.xml