本文翻译自:https://developer.android.com/guide/topics/ui/themes.html
Style和theme词汇是专用术语,下文直接使用而不翻译。
样式和主题(Styles and Themes)
一个样式(Style)是一个包含了指定样子和格式的作用于视图控件(View)或者窗体(Window)属性集合。一个style可以指定很多属性,比如 高度,填充,字体颜色,字体尺寸,背景色等。一个Style在xml资源文件中定义,并且和在xml中指定的布局区分开来。
在Android里的样式和Web设计中的CSS共享一个相似的原理,它们允许你分离设计(Design)和内容(Content).
举个例子,通过使用一个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" />
所有关联到style的属性已经在布局xml中被删除了,并且放在一个叫做“CodeFont”style中定义了。它通过一个style属性被应用上。在下面的章节,你将会看到如何定义style。
一个主题(Theme)也是一个style,它被应用在所有的Activity或者application上,而不是个别的视图控件(View)(像上面的示例一样)。当一个style被当做一个theme来应用,每一个activity或者application中的视图控件将应用每一个它支持的样式属性。比如,你可以在activity上使用相同的CodeFont样式作为一个theme,这时Activity里的所有内部字体将会变成CodeFont样式的字体样式变成绿色的等宽字体。
定义一个样式Style
为了创建一些样式,你可以保存在你的工程下的 res/Values/ 文件夹下的一个XML文件中。XML文件的名字是随意的,但是必须扩展名是 .xml 并且存放在 res/Values/ 文件夹下。
XML文件的根节点必须是<resources>
为你创建的每个样式,添加一个<style>元素,并且需要一个name 属性,它标识唯一性而且是必需的属性。再为你的样式属性都添加进去,通过添加<item>元素来做,使用一个在样式属性里声明的name属性和一个value属性,这两个都是必需的。<item>的value属性可以是一个关键字字符串,一个16进制的颜色描述,一个其他资源类型的引用,或者在其他样式属性中依赖的value。下面是一个简单的示例样式文件内容:
<?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属性的值(value)来被引用引用。这个示例样式可以在XML布局中被引用,比如“@style/CodeFont”(像上面介绍的示例一样)。
在<style>元素中的parent属性是可选的并且指向一个其他样式中的资源ID,它可以从这个样式中继承一些属性。合适的话,你可以重写(override)继承到的属性。
记住,一个你想在activity或者application中使用的样式都被在XML文件中定义,并且所有的视图控件具有相同的样式。一个样式,比如上面定义的那个,可以被作为一style应用的单一的视图控件上或者被作为一个theme应用在全部的activity或者application上。如何应用的单一的视图或者作为应用的主题,我们稍后讨论。
继承
在<style>中的parent属性让你可以指定一个你可以继承其属性的样式。你可以使用这个从一个已经存在的样式中继承属性,并且定义一些独有的你需要改变或者添加的属性。你可以继承那些来自你已经自行创建的样式或者或者继承自在平台里构建好的样式(See Using Platform Styles and Themes,下面,获得关于继承安卓平台样式的更多信息)。比如,你可以继承安卓平台默认的字体样式并且修改它,比如:
<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(这是个你已经定义好的样式)这个样式名开始的,这个样式从哪个样式里继承了所有的样式属性。这个样式这里覆盖里android:textColor属性,将文本改成了红色。你可以引用这个新的样式比如@style/CodeFont.Red。
你可以继续这样继承很多次,使用“点”链接这些名称,比如,你可以扩展CodeFont.Red 变大一些,像下面这样:
<style name="CodeFont.Red.Big"> <item name="android:textSize">30sp</item> </style>
这里从CodeFont和CodeFont.Red继承了,又添加了 android:textSize 属性
注意:这样的通过链接名称的方式来继承的方法,仅仅能用于你自己定义的资源文件中的样式。你不能用于继承安卓内置的样式。要想引用内置的样式,比如TextAppearance
,,你必须使用parent属性。
样式属性
现在,你明白了如何定义一个样式,你需要去学会 在<item>元素下什么类型被定义的样式属性是可用的。你可能已经熟悉了很多已经有的,比如layout_width
和 textColor
. 当然,还有很多的样式属性你可以使用。
寻找可以应用在指定视图控件上的属性的最好的地方是 相应的类引用,它列出了所有支持的XML属性。比如所有在表格 TextView XML attributes 中列出的属性,都可以应用在一个样式的定义中作用在TextView元素上(或者它的子类)。在 引用 中被列出的一个属性叫做android:inputType的,这样你可以再<EditText>元素中应用这个属性,像下面这样:
<EditText android:inputType="number" ... />
你可以为EditText 元素创建一个样式,包含这个属性,来代替上面:
<style name="Numbers">
<item name="android:inputType">number</item>
...
</style>
这样你的布局用的XML能够这样实现样式:
<EditText style="@style/Numbers" ... />
这个简单的示例看起来多做了一些工作,不过当你添加更多的样式属性并且把在多处可重用样式的能力作为参考因素的话,你的付出将是值得的。
获得所有可用样式的属性的引用(reference),请参阅 R.attr
引用。记住,所有的视图控件对象不接受所有相同的属性,这样你可以平常的引用图为视图控件类指定支持的样式属性。然而,如果你为某个视图控件应用了一个样式,这个样式包含的属性中不是都被支持的,视图控件将会应用那些属性中的可被支持的并且简单的忽略其他的。
一些样式属性,不被支持在视图控件里使用,仅仅能作为主题使用。那些样式属性应用在所有的窗体上,不能用在任何视图控件上。比如有些样式属性可以隐藏应用程序的标题,隐藏状态条,或者更改窗体的背景。那些类型的样式属性不属于任何视图控件对象。要发现更多 仅仅作用于theme主题 的属性,查看R.attr
引用中的以windows开始的属性。比如,windowNoTitle
和 windowBackground
属性只能在应用于activity和application时发生作用。参阅下一章节可以获得更多“在theme中应用样式”的内容。
注意:在<item>元素中,不要忘记写属性名称的前缀 android: ,这是一个命名空间,比如:
<item name="android:inputType">
.
在UI上应用样式和主题
有两种方式设置一个样式:
- 为单个视图控件指定样式,在XML布局文件中的视图元素上添加style属性。
- 为整个activity或者application指定样式,在manifest.xml中的<activity>或者<application>节点元素中添加
android:theme 属性。
当你为布局里的单个控件中应用一个样式,你的样式中定义的属性都会应用在这个视图组件中。如果你的样式应用在一个ViewGroup中,它的所有子控件元素将不能继承这些样式的属性,只有你直接指定的那个视图元素可以应用这些属性。不过,你仍然可以通过主题的方式为你的应用下的所有视图元素应用样式。
要想应用一个主题,你必须在manifest.xml中为activity或者aplication上应用样式。当你这么做,每一个Activity或者aplication里的视图元素都将应用这些样式中它支持的属性。比如,如果应用上面提到的CodeFont样式在一个Activity上,这是所有的支持文本样式属性的视图元素将应用它们。一些不支持这些属性的视图元素将忽略它们。如果一个视图支持一部分属性,那么它将只应用这些属性。
在视图元素中应用样式
下面演示如何在XML布局中设置一个样式:
<TextView style="@style/CodeFont" android:text="@string/hello" />
现在 TextView将具有样式,像CodeFont定义的属性描述的一样。你可以参考上面的示例。
注意:样式style 不需要使用androidoi: 命名空间前缀。
在activity或者application中应用样式
要想再你的所有activity或者application上使用样式,打开 AndroidManifest.xml
并且修改<application>标签,让它包含 android:theme
属性并指定一个样式名称,比如:
<application android:theme="@style/CustomTheme">
如果你想为你的应用中的某个activity使用样式,那么添加 android:theme
到你的<activity>标签中。
安卓提供了一些内置资源,你可以使用这些预先定义好的样式,而不用自己再重新写了。比如,你可以使用Dialog主题让你的Activity 表现的像一个 对话框:
<activity android:theme="@android:style/Theme.Dialog">
或者你想让你的背景透明,使用 透明主题:
<activity android:theme="@android:style/Theme.Translucent">
如果你喜欢主题,但是想开足马力使用它,那么你可以添加它到你的自定义主题中的parent属性上继承它。比如,你可以修改 传统的 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>
注意上面用到的颜色在其他资源中被提供,这里,因为android:windowBackground 属性仅仅支持其他资源的引用,不像 android:colorBackground属性可以指定一个颜色描述文本。
现在,在你的Mnaifest文件中,可以使用 CustomTheme
代替 Theme.Light:
<activity android:theme="@style/CustomTheme">
选择一个平台支持的样式作为基础
安卓较新的版本为应用提供了额外的可用的样式,同时你可能想要使用它们在那些平台上运行,并且仍然和老版本保持兼容。你可以通过自定样式做到,使用“资源选择器"来切换不同的父主题,基于平台版本。
比如,下面是一个自定义样式的声明,这个样式是个简单的标准平台默认的 light theme主题。它可能被放置在res/valeus文件夹下的 XML文件中(经典的是在 res/values/styles.xml)。
<style name="LightThemeSelector" parent="android:Theme.Light">
...
</style>
当应用跑在Android 3.0(API级别11)或者更高以上时,可以让这个样式使用较为新一些的holo风格主题,你可以放置一个可供选择的声明样式防止在res/values-v11这个文件夹下的XML文件中,但是让这个样式继承自 holo风格的主题:
<style name="LightThemeSelector" parent="android:Theme.Holo.Light">
...
</style>
现在可以像任意其他那样来使用这个主题,并且当跑在安卓3.0以上时,你的应用程序会自动切换到holo风格的主题。
在 R.styleable.Theme
. 里,可以找到一个标准的属性列表供你使用。
关于更多的信息,像比如主题和布局,基于平台版本或者设备配置等切换资源文件选择,你可以阅读 Providing Resources 。
使用平台样式和主题
安卓平台提供了很多样式和主题,供你在应用程序中使用。在 R.style
类里你可以找到可以用的引用。为了使用这里列出的样式,你可以使用”点“替换所有的下划线分割的 样式名称,比如,你可以通过”"@android:style/Theme.NoTitleBar"
.来使用 Theme_NoTitleBar
样式。
R.style
引用,然而,不是和好的文件记录,并且不能全面的描述样式,那么查看那些样式和主题的实际的资源代码可以给你更好一些关于”各个被提供样式属性“的的理解。获得更多关于样式和主题的引用,你可以看下面的源代码:
那些文件将通过实例帮助你学习。比如,在安卓的主题源代码中,你将找到一个声明 <style name="Theme.Dialog">
.在这些定义里,你将会看到所有的常常用到的 ”被用于安卓框架的样式对话框的属性“
更多关于 样式和主题 在XML中的语法的信息,请参阅 Style Resource 文档。
对于 一个可用的样式属性的引用,你可以它使用定义一个样式或者主题(比如"windowBackground" 或者 "textAppearance),在你创建一个样式时你可以阅读 R.attr
或者各自的视图类。