这里翻译的是android文档中API Guides下的styles and themes,原文网址:http://developer.android.com/guide/topics/ui/themes.html
翻译的时候发现有些内容略显重复,所以做了一些删减,但是内容是完整的。另外翻译是意译。
对于一个视图(View)和一个窗口(Window)来说,会有一些属性指定他们的外形和格式,style就是这种属性的集合。style可以用来定义height, padding, font color, font size, background color等等属性。style定义在一个xml格式的资源文件中,这个资源和布局文件是分开的。
在Web开发中有级联样式表,android中的styles和这个有着类似的理念,都是允许开发人员将设计和内容分开。
例如,要应用一个样式,你可以在布局文件中这样定义:
<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中定义,在接下来的部分中你将会看到这个CodeFont的定义。
主题(theme)就是一个应用在整个Activity或者Application中的style,而不是应用于个别的View。当一个style被作为一个Theme应用于Activity或者Application中时,Activity或者Application中的每一个View都会被应用这个style所提供的属性。例如,你可以将上面的CodeFont样式作为一个Theme应用在一个Activity中,这样这个Activity中的所有文字都会使用monospace字体。
定义样式(Styles)
为了创建一个样式的集合,你需要在你的工程的res/values/目录下新建一个xml文件,文件名可以随意,但是必须是.xml后缀,而且并需位于res/values/目录下。
文件的根节点必须是<resources>。
对于你想创建的每一个style,需要添加一个<style>子元素,并且name属性是必须的而且要唯一。然后添加一个<item>子元素来定义一个样式属性,item节点的name属性也是必须的,item的值可以是一个string,hex color或者到另外一个资源类型的引用,以下是一个含有一个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>节点的每一个子节点在编译时都被转换成一个应用资源对象,这个对象可以通过子节点的name属性引用,上面的示例中的style可以在xml布局文件中这样引用:@style/CodeFont。
<style>节点有个parent属性,它指向另一个style,当前style继承parent属性引用的style,在当前style中可以覆盖父style中的样式定义。
请记得,无论style是应用于Activity、Application或者只是一个View,他们都在同一个styles.xml文件中定义。一个style如何应用在一个View或者一个Application将在下面讨论。
继承
style中的parent属性允许你定义一个style以供其他style继承,你可以利用这个特性,继承一个已经存在的style,然后只更改或者添加那些你想要控制的样式。你可以继承自己定义的style,也可以继承系统内置的style(详情见下面关于 Using Platform Styles and Themes的讨论),例如,你可以继承android 平台定义的文字外观样式然后修改它:
<style name="GreenText" parent="@android:style/TextAppearance">
<item name="android:textColor">#00FF00</item>
</style>
如果你想要继承你自己定义的style,你也可以不通过使用style的parent属性,取而代之,只是用被继承的style的name值作为新style的name值的前缀,后面跟上新style的name值。比如:你希望创建一个新的style继承上面的CodeFont样式,然后将颜色改成红色,你就可以这样写:
<style name="CodeFont.Red">
<item name="android:textColor">#FF0000</item>
</style>
请注意这个style并没有parent属性,但是它的name属性值以上面的样式style的name值开头,这个新的style同样继承了上面CodeFont的所有特性,你可以使用@style/CodeFont.Red来引用这个新的style。
你可以继续继承CodeFont.Red然后更改其中的字体大小,就像下面这样:
<style name="CodeFont.Red.Big">
<item name="android:textSize">30sp</item>
</style>
注意:这种继承方式只适用于你自己定义的style,如果是继承android内置的style还是必须通过style的parent属性。
样式属性(Style Properties)
现在你已经知道了如何定义一个style,接下来你需要知道都有哪些样式属性可以通过style的item子节点定义,可能有些你已经见过了,像layout-width和textColor,当然还有很多你可以使用的样式属性。
寻找适合特定视图(View)的样式属性的最好的地方就是对应的类的API (android开发文档中的reference),在那里列出了这个View子类所有可用的样式属性。例如:所有在TextView xml 属性都可以在style中定义,看下面的一个EditText的例子:
<EditText
android:inputType="number"
... />
你可以创建一个style,将android:inputType放在style中定义:
<style name="Numbers">
<item name="android:inputType">number</item>
...
</style>
然后之前的布局文件中写法就可以替换成一下这样:
<EditText
style="@style/Numbers"
... />
上面的例子过于简单以至于看上去我们做了很多额外的工作,但是需要定义的样式属性变得很多的时候,你就可以通过定义style来实现重用,这个时候额外的付出就是值得的。
R.attr reference列出了所有可用的样式属性,但是要知道,一个View Object并不是所有样式属性都可用,所以你应该只定义那些它能够支持的。如果你在一个style中定义了一些当前View不支持的样式属性,这个View在应用样式的时候只会应用那些它支持的而忽略那些它不支持的。
有些style样式属性,所有的View都不支持,他们只用来作为一个Theme,这些样式属性应用在整个Window而不是单个View。例如,一个Theme中的样式属性可以隐藏应用标题,隐藏状态栏或者改变窗口的背景颜色,这些是哪个不属于任何一个View。想发现这些只用于Theme中的样式属性,可以查看R.attr reference中那些以window开头的属性,windowNoTitle 和 windowBackground 等,这些属性只在style作为一个Theme应用于一个Activity或Application中,下一部分将详细讲解style作为Theme如何使用。
注意:不要忘了item中的name属性值需要带上android:命名空间,示例:
<item name="android:inputType">
在UI中应用样式和主题(Applying Styles and Themes to the UI)
有两种方式设置一个样式:
1、对于一个单独的View,通过向布局文件中的View控件添加style属性来应用一个style。就像下面:
<TextView
style="@style/CodeFont"
android:text="@string/hello" />
注意:style前面没有android:前缀。
2、对于一个Activity或者Application,在manifest文件中的Application或者Activity标签中添加android:Theme属性来设置样式。
当你将定义的style应用到一个View中时,style中定义的属性只会影响到这一个View。当你将style应用到一个ViewGroup中时,这个ViewGroup中的子View并不会继承它的style。
要将一个style作为Theme,你需要将style应用在manifest文件中的Activity或者Application中,当你这样做时,Activity或者Application中的每个View都会被应用这个style。举例来说,如果你将之前定义的CodeFont样式应用在一个Activity上,所有这个Activity中的View都会被应用这个样式(每个View只会应用它自己支持的样式,不支持的那些就忽略)。
给一个Application应用style:
<application android:theme="@style/CustomTheme">
给一个Activity应用style:
<activity android:theme="@style/CustomTheme">
android平台本身也提供了很多内置的Theme,例如你想使用android平台的Dialog主题以便你的activity看起来像一个对话框,你可以这样:
<activity android:theme="@android:style/Theme.Dialog">
或者你想让背景变得透明,你可以使用透明主题:
<activity android:theme="@android:style/Theme.Translucent">
如果你想使用一个主题,但是又想稍微做些调整,你可以自己写个style来继承它,例如:
<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不同,它可以直接定义一个颜色值。
现在就可以在manifest文件中使用这个主题:<activity android:theme="@style/CustomTheme">
根据系统版本选择主题(Select a theme based on platform version)
更新版本的系统会添加一些新的Theme,你可能希望当你的应用运行在新版本的系统中时使用它们,同时不影响之前版本中的显示样式,这样的功能可以通过给资源文件夹带上版本信息来实现。下面是一个示例:
一般情况下你想要定义一个主题并继承系统的某个主题,你会到res/values目录下的某个样式文件(一般是styles.xml)中这样定义:
<style name="LightThemeSelector" parent="android:Theme.Light">
...
</style>
当应用运行在android 3.0(API版本是11)或更高版本时你想让LightThemeSelector继承另一个新的style(在3.0版本中新加入的),
你可以在res/values-v11目录下的styles.xml文件中定义一个相对的style:
<style name="LightThemeSelector" parent="android:Theme.Holo.Light">
...
</style>
这样一来,当你的应用运行在3.0或更新版本的系统上时,LightThemeSelector就会继承
Theme.Holo.Light这个主题。
在R.styleable.Theme中你可以看到你能在Theme中使用的标准属性列表。
想要获得更多与特定版本相关的Themes 和 styles的信息,可以查看文档 Providing Resources
使用平台的styles和themes(Using Platform Styles and Themes)
android 平台提供了很多可以用在app中的styles和themes,你可以在android文档中的R.style里看到所有可用的styles参考。要直接使用系统的styles需要按照如下格式来写:"@android:style/Theme.NoTitleBar" 这样就应用了Theme.NoTitleBar这个系统提供的style。
R.style并不是最好的文档,因为它只是列举了系统中的styles加上一些简单描述,最好的文档是查看系统中对这些styles进行定义的文档,你可以在以下位置找到这些定义文件:
android styles:[你放置android-sdk的目录]android-sdk\platforms\android-21\data\res\values\styles.xml
android themes:
[你放置android-sdk的目录]android-sdk\platforms\android-21\data\res\values\themes.xml
在这些文件中你可以看到系统中的styles和themes是如何定义的以及都定义了那些属性。