概述:
Style(样式)是一系列指定View或者window长相和格式的属性. Style可以指定的属性比如高度(height),填充(padding), 字体颜色(font color), 字体大小(font size), 背景色等. 一种style可以定义在XML资源文件中. 这东西的设计理念就是将UI设计和内容设计分离. 比如通过style我们可以将这个layout文件:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#00FF00"
android:typeface="monospace"
android:text="@string/hello" />
改造成这样:
<TextView
style="@style/CodeFont"
android:text="@string/hello" />
所有跟style有关的属性都被从layout文件中移除, 并存入一个名为CodeFont的style定义文件中.
主题(Theme)则是应用于整个Activity或者APP的样式, 而不是单个View. 当style在APP内部形成了统一的风格, 那么就成了一个主题. 比如我们可以将CodeFont作为一个主题设置给一个Activity, 这样所有的TextView就有了一样的样式.
定义style:
想要定义一组style, 我们需要在res/values/目录下创建XML文件. 文件名字没有限制, 但是后缀名必须为.xml. 该文件的根标签为<resources>. 对于我们想创建的每个style, 必须为其指定<style>标签并带有一个唯一的标识, 该标识使用name指定. 然后为style的每个属性增加<item>标签, 同样需要指定name作为style的属性, 然后为<item>指定该name的值, 该值可以是一个关键字的字符串, 一个十六进制的颜色, 一个到其它资源文件的关联信息, 或者其它可以接受的值, 这里是一个栗子, 它包含一个单独的style:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CodeFont" parent="@android:style/TextAppearance.Medium">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#00FF00</item>
<item name="android:typeface">monospace</item>
</style>
</resources>
<resources>标签的每个子标签都会在编译的时候被转化为一个APP资源对象,可以通过style的name属性的值来关联. 上面这段代码中的style可以在一个XML layout文件中使用@style/CodeFont关联它.
而<style>中的parent属性是一个可选的属性, 它指定了要继承的样式的资源ID, 如果需要的话我们可以重写继承的样式属性.
而theme的写法跟style是一样一样的. 像上面这样的style文件可以作为style应用于某个View, 也可以作为theme作用于某个Activity或者整个APP.
继承性:
<style>中的parent属性为我们指定了一个可以继承其属性的style. 我们可以使用该属性来继承一个现成的style, 然后修改或者增加我们需要改变的属性. 我们可以继承我们自己的style, 也可以继承平台提供的已有的style. 比如这里是一个继承平台style的栗子, 我们可以修改它的默认textColor:
<style name="GreenText" parent="@android:style/TextAppearance">
<item name="android:textColor">#00FF00</item>
</style>
如果我们想要继承的style是我们自己写的, 那么我们不一定非要使用parent属性, 而是只需要使用想要继承的style的名字作为前缀并用圆点来分隔我们新的style的名字即可. 比如我们想要创建一个继承自CodeFont的新的style, 但是修改textColor为红色, 那么我们可以这样写:
<style name="CodeFont.Red">
<item name="android:textColor">#FF0000</item>
</style>
这里并不需要一定指定parent属性, 但是因为name属性是以CodeFont开头的(前提是该style已经被我们创建了), 所以新的style继承了CodeFont的所有的属性. 然后新的style重写了android:textColor属性使字体颜色变为红色, 我们可以通过@style/CodeFont.Red来使用这个新的style.
我们还可以对CodeFont继续继承, 还可以扩展它的样式, 比如:
<style name="CodeFont.Red.Big">
<item name="android:textSize">30sp</item>
</style>
新的样式继承了CodeFont和CodeFont.Red的属性, 然后还增加了自己的android:textSize属性.
这种模式只能用于继承我们自己的style. 我们不能使用这种方法来继承Android的自带style. 想要继承Android自带的style必须使用parent属性.
Style属性:
现在已经了解<style>, 那么该了解一下style的属性了, 也就是<item>. 我们应该对一些常用的已经很熟悉了, 比如layout_width和textColor. 当然还有很多我们可以使用的属性. 最好的了解每种View可以使用的属性的地方是它们的class reference, 那里有它们所有的可以支持的XML属性. 比如TextView(以及其子类)的可以使用的全部style定义在TextViewXML attribute中. 这里面包含一个android:inputType属性, 所以我们可以在<EditText>中使用androi:inputType像这样:
<EditText
android:inputType="number"
... />
这样我们就可以为EditText创建一个带有该属性的style:
<style name="Numbers">
<item name="android:inputType">number</item>
...
</style>
所以我们的XML可以通过指定style写成这样:
<EditText
style="@style/Numbers"
... />
这个栗子很简单, 使用style好像还做了更多的事情, 但是如果我们的代码和控件都很多的时候, 使用style可以帮我们节省很多时间.
对于那些可以应用于所有的属性的style可以参考R.attr.但是我们应该记得不是所有的View对象都可以接受所有相同的style的, 所以通常我们应该为指定的View类提供指定的可以支持的style. 如果我们一意孤行的为一个View指定了它不能支持的style属性, 其实也没啥事, 它们会选择自己支持的生效, 不支持的就忽略了.
有些style属性则不能支持任何View而只能应用于theme, 这些style属性应用于整个window而不是应用于任何View. 比如, 有的style属性可以隐藏application title, 隐藏status bar, 或者改变窗口背景. 这些类型的style属性不属于任何View对象. 这些只能应用于theme的style属性可以到R.attr中的以window开头的属性中查看. 比如windowNoTitle和windowBackground就是只能作为theme应用于一个Activity或者APP的style属性.
另外切勿忘记<item>标签中的name属性需要用android:作为前缀, 比如<item name=”android:inputType”>.
将style和theme应用于UI:
有两种方式可以设置一个style:
第一种是对一个独立的View, 通过在XML文件中对View标签增加style属性.
第二种是针对整个Activity或者APP, 通过在manifest文件中对<activity>或者<application>增加android:theme属性.
当我们对一个独立的View使用style的时候, style中的属性只是应用于该View自己. 如果style是应用于一个ViewGroup, 那么它的子View却不会继承这个style, 只有直接应用的标签才会使用style, 然而我们可以通过将style作为theme应用于全部的View.
想要将style作为一个theme使用, 我们必须在manifest文件中将style应用于一个Activity或者application. 当我们这样做的时候, 在Activity或者application中的每个View都会使用style中它们可以支持的属性. 比如如果我们将CodeFont应用于一个Activity, 那么所有支持text style属性的View标签都将使用这个style. 不支持的则会忽略它.
将style应用于一个View:
我们可以这样将style应用于一个View:
<TextView
style="@style/CodeFont"
android:text="@string/hello" />
这样这个TextView就会使用这个名为CodeFont的style了. 注意style属性不使用android:作为前缀.
将style应用于一个Activity或者application:
想要为application中的所有Activity设置一个theme, 我们需要在AndroidManifest.xml文件中编辑<application>标签, 并为android:theme指定一个style名字, 比如:
<application android:theme="@style/CustomTheme">
如果我们想要这个theme应用于单个的Activity, 那么只需要为<activity>增加android:theme属性即可.
就好像Android提供的其它内置资源一样, 我们也同样有很多内置的theme可以使用. 比如我们可以使用Dialog theme使Activity以dialog的形式显示:
<activity android:theme="@android:style/Theme.Dialog">
或者如果我们想要使背景透明, 可以使用半透明(Translucent)主题:
<activity android:theme="@android:style/Theme.Translucent">
如果我们喜欢某个主题, 但是想改造它, 那么只需要将该主题作为parent再自定义自己的主题就可以了, 比如我们可以修改traditional light theme来使用我们自己的颜色:
<color name="custom_theme_color">#b0b0ff</color>
<style name="CustomTheme" parent="android:Theme.Light">
<item name="android:windowBackground">@color/custom_theme_color</item>
<item name="android:colorBackground">@color/custom_theme_color</item>
</style>
需要注意这里的color资源需要作为一个独立的资源, 因为android:windowBackground属性只支持使用其它的资源, 不像android:colorBackground,它不能直接使用#b0b0ff这样的文本形式. 然后我们就可以使用我们的CustomTheme代替Theme.Light了:
<activity android:theme="@style/CustomTheme">
选择一个基于平台版本的主题:
新版本的Android通常会提供新的主题, 如果我们希望自己的APP可以使用这些主题, 并且在旧版本的Android上也可以表现良好的话, 那么我们可以考虑基于平台版本来改变APP的主题. 比如这里是一个自定义主题的声明, 它只是简单的继承了Android内置的Theme.Light主题, 它将会存放在res/values目录下(通常是res/values/styles.xml):
<style name="LightThemeSelector" parent="android:Theme.Light">
...
</style>
我们又想要在Android3.0及以上版本的时候使用Holo主题, 那么我们可以在res/values-v11目录中添加一个额外的theme文件, 但是使用Holo作为parent:
<style name="LightThemeSelector" parent="android:Theme.Holo.Light">
...
</style>
这样我们的theme就可以在Android3.0及以上版本中自动使用Holo主题了. 可以在R.styleable.Theme中查找在theme中可用的标准属性.
使用内置的style和theme:
Android为我们提供了大量的可用的style和theme. 我们可以在R.style中查找可用的style. 想要使用任何一个内置的style,只需要将它们名字中的下划线换成圆点就可以了, 比如我们可以通过”@android:style/Theme.NoTitleBar”来使用Theme_NoTitleBartheme.
由于R.style中的文档描述的并不咋好, 所以官方建议我们通过阅读style的源码来了解它们都提供了什么属性, 这里是源码的地址:
这些文件将会帮我们学习里面的栗子, 比如在android theme的源文件中我们将会找到<style name=”Theme.Dialog>的声明, 在这里将可以看到所有应用于styledialog的属性.
总结:
我们可以通过style和theme为Android指定统一的风格. 它们都是style, theme是应用于Activity或者application的style.
使用流程: 首先在res/values/下简历styles.xml文件, 然后在layout中引用它们, 如果想要应用于整个Activity或者application则需要在manifest文件中指定android:theme属性.
参考: http://developer.android.com/guide/topics/ui/themes.html