样式(style),是为一个视图(View)或窗体(window)指定形状和格式的属性集。一个样式能够指定的属性包括高度、内边距、字体颜色、字体大小、背景颜色等等。样式被定义在一个XML资源文件中,跟设置布局的XML资源文件是分开的。
Android中样式的设计哲学跟web设计中的CSS(层叠样式表)相似,就是想办法让设计和内容分隔开来。
例如,通过使用样式(style),你可以将下面的XML布局:
<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" />
所有的属性都联系到一个从布局文件中分离的样式并且放到一个叫做CodeFont
的标签定义中,然后使用style
属性应用到布局中。在下面的板块中,我们将会学习到style
标签的定义。
主题(theme)是应用到整个活动(Activity)或应用(application),而不是单单一个视图(正如楼上的例子一样)。当一个样式被用作主题时,所有在Activity或application中的view将应用每一个它所支持的样式属性。例如,你可以应用
CodeFont
样式作为一个Activity的主题,之后所有包含在这个Activity中的text将会是绿色的monospace字体。
一、定义样式
为了创建一个样式集,需要在你的项目的res/values
目录中新建一个XML文件。这个XML文件可以随意命名,但是要以.xml
为扩展名并且保存在res/values
文件夹中。这个XML文件的根节点必须是<resources>
。
对于每一个你建立的样式,你需要添加一个带有独一无二的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>
的子元素在编译的时候都会转化成一个应用资源对象,通过<style>
元素的name
属性被引用。示例中的style可以作为@style/CodeFont
被XML布局调用(正如楼上的引言展示的)。
<style>
元素的parent
属性是可选的,它说明了另一个style的ID(当前样式从中继承了属性)。如果你愿意,你可以重写父样式的属性。
请牢记,定义在XML中用作Activity或者application的主题的style跟用作View的样式的style是一样的。正如上面定义的一样,一个style既可以应用于单个View,也可以应用于整个Activity或者application。具体如何使用,我们稍后讨论。
二、继承(Inheritance)
<style>
元素的parent
属性需要你指明你的样式是要从哪个样式里继承属性。你可以使用它从已有的style中继承属性,然后只定义你想要改变或者添加的属性。style既可以继承自你自己创建的style,也可以继承自平台内建的style。(关于这点,下文会详细讨论)例如,你可以继承自Android平台默认的文本外观(text appearance),然后修改它。
<style name="GreenText" parent="@android:style/TextAppearance">
<item name="android:textColor">#00FF00</item>
</style>
如果你想要继承自自定义的样式,那你大可不必使用parent
属性。取而代之,你可以父样式的名字作为新样式的前缀,用英文的点号“.”隔开。例如,为了创建一个继承自上文定义的CodeFont
样式的新样式,颜色改为红色,你可以这样子写:
<style name="CodeFont.Red">
<item name="android:textColor">#FF0000</item>
</style>
需要说明的一点是在<style>
标签中并没有parent
属性,但是因为name
属性是从CodeFont
样式名开始的,所以这个样式就继承了CodeFont
样式的所有属性。新样式重写了android:textColor
属性,从而使文本变红色。你可以通过@style/CodeFont.Red
使用这个新样式。
你可以像这样通过改变name多次继承。例如,你可以扩展CodeFont.Red
使得字体变得更大:
<style name="CodeFont.Red.Big">
<item name="android:textSize">30sp</item>
</style>
这样子就继承了CodeFont
样式和CodeFont.Red
样式,并添加了android:textSize
属性。
小贴士:这个技巧只在自己定义的样式生效。你不可以用于Android内建的样式中。引用内建的样式,比如
TextAppearance
,你必须使用parent
属性。
三、样式属性(Style Properties)
现在你知道了样式是如何定义的,你还需要学习<item>
元素中有哪些样式属性。你可能对一些属性比较了解,比如layout_width和textcolor。然而,还有更多的属性你可以使用。
发现应用于特定View的属性的最好地方是找到相应的类参考文档(class reference),它会列出所有支持的XML属性。例如,列在TextView XML attributes表中的所有属性可以用作TextView元素(或者它的子类)的样式定义中。列在其中一个属性是android:inputType
,所以你可以很正当地在<EditText>
元素中写下android:inputType
属性,就像这样:
<EditText
android:inputType="number"
... />
取而代之,你也可以为EditText
元素创建一个style来包含这些属性:
<style name="Numbers">
<item name="android:inputType">number</item>
...
</style>
然后你的XML布局就可以实现这个style了:
<EditText
style="@style/Numbers"
... />
这个简单的例子看起来很多余,但是当你添加更多的样式属性并且使得它可以在不同的地方重用这个样式,回报是巨大的。
要想知道所有可用的style属性,你可以参看这里R.attr。你得牢记于心的是并不是所有的View对象都接受相同的style属性,所以你应该参照一下特定的View类所支持的样式属性。然而,当你应用一个style到View中,而这个View并不支持所有的style属性,那么这个View只会应用那些支持的属性而忽略其它不支持的。
有些style属性并不支持任何的View,而只能用作theme。这些style属性应用到整个的窗体而不是任何类型的View。例如专门用于theme的style属性可以隐藏应用标题,隐藏状态栏或者改变窗体的背景。这些样式属性并不属于任何一个View对象。为了找到这些theme专用的样式属性,你可以参见R.attr
中以window
开头的属性。比如说,windowNoTitle
和windowBackground
是只当style应用于Activity或application的主题时生效的style属性。看看下一个版块,了解如何应用一个style到theme。
小贴士:不要忘记给每个
<item>
元素添加android:
命名空间作为前缀。例如:<item name="android:inputType">
四、应用样式和主题到UI中
有两种方法来设置style:
- 对于单个的View,你可以通过在XML布局中添加
style
属性到一个View元素中; - 或者,对于整个Activity或application,可以通过在Android manifest文件中添加
android:theme
属性到activity
或application
元素。当你应用一个样式到布局中单个的
View
,样式中定义的特性只会应用到这个View
。如果一个样式被应用到一个ViewGroup
,那么在其中的孩子View
将不会继承这些样式——只有你直接应用样式的元素才会应用样式中的特性。但是,你可以通过将样式作为主题使用来达到对所有的View
元素使用同一种样式。
为了应用一个style定义作为主题,你必须在Android manifest文件中为
Activity
或application
应用该样式。之后,在Activity或者application中的每个View将会应用每一个它们所支持的样式特性。例如,你应用上面所说的CodeFont
样式到一个Activity
中之后,所有的支持这个文本样式特性的View
元素将会应用之。任何不支持这个特性的View
将会忽略它们。假如有个View
只支持部分的特性,那么它将只应用那部分的特性。
应用一个样式到View中
这里有个例子,关于如何在XML布局中为一个View设置样式的:
<TextView
style="@style/CodeFont"
android:text="@string/hello" />
现在,这个TextView
就应用了一个叫CodeFont
的样式(见上面的例子)
小贴士:
style
属性不需要用android:
命名空间前缀。
应用一个主题到Activity或application中
为了给你的应用中的所有Activity设置一个主题,你需要打开AndroidManifest.xml
文件,然后编辑<application>
标签,写上android:theme
属性,用样式名作为它的值。例如:
<application android:theme="@style/CustomTheme">
如果你想要单单为应用中的某个Activity设置主题,你只需要将上述的标签改为<activity>
就行了。
正如Android提供了其他的内建资源,为了减少开发人员的麻烦,它也提供了需要预定义的主题给你用。例如,你可以使用Dialog
主题使得你的Activity看起来像一个对话框:
<activity android:theme="@android:style/Theme.Dialog">
或者如果你想要使背景透明,可以使用Translucent theme:
<activity android:theme="@android:style/Theme.Translucent">
如果你喜欢一个整体,但是想要调整它,你只要将它作为你自定义主题的父主题(parent
)就行了。例如,你可以修改默认的亮主题以使用你自己的样式:
<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>
(提示:这里的颜色需要提过一个独立的资源。因为android:windowBackground属性只支持到另一个资源的引用;不像android:colorBackground,它不能通过十六进制的颜色值来设置)
现在在Android Manifest使用CustomTheme取代Theme.Light
<activity android:theme="@style/CustomTheme">
选择一个基于平台版本的主题
新版本的Android 有附加的主题可以用到你的应用中,以便于兼容老的版本。你可以基于当前版本使用资源选择器在不同的父主题中切换来自定义主题以达到兼容的目的。
例如,这里有一个对于标准平台默认的亮主题的自定义声明,写在res/values
文件夹下的一个XML文件中(一般是res/values/styles.xml
)
<style name="LightThemeSelector" parent="android:Theme.Light">
...
</style>
为了使当应用运行在Android 3.0(API Level 11)或者更高版本时可以用上新的全息主题,你可以放置一个对主题备选的声明的XML文件在res/values-v11
,父主题要改为全息主题:
<style name="LightThemeSelector" parent="android:Theme.Holo.Light">
...
</style>
现在使用这个主题就像您任何其他的,如果在Android3.0或更高版本上运行你的应用程序会自动切换到全息主题。
有一个标准属性表,显示了所以你可以在主题中使用的属性,你可以在R.styleable.Theme中找到。
更多有关提供替代资源,比如主题和布局的基础上,平台版本或其他设备配置的详细信息,请参阅参考 Providing Resources文档。
五、使用平台样式和主题
Android平台提供了一个很大的样式和主题集,以便于你可以在你的应用中使用。你可以在R.style类中找到一个所有可用的样式的参考。为了使用列表中的样式,用一个英文句号取代在样式名中的所有下划线(?)。例如,你可以用"@android:style/Theme.NoTitleBar"
来应用Theme.NoTitleBar
主题。
然而,R.style参考并不是文档齐全的,它没有完全描述这些样式,所以看这些样式和主题的源代码会让你更好的他们各自提供的样式特性。在下面可以看到:
这些文件会帮助你通过例子学习。例如,在Android themes源代码中,你会发现一个<style name="Theme.Dialog">
的声明。在这个定义中,你会看到所有用于样式化被Android框架调用的对话框。
更多有关样式和主题的语法,常见Sytle Resource。
关于可用来定义样式和主题的样式属性(比如,“windowsBackground”或“textAppearance”)的参考,参看R.attr或者你要创建样式的View类。