样式
样式是指为 View 或窗口指定外观和格式的属性集合。样式可以指定高度、填充、字体颜色、字号、背景色等许多属性。 样式是在与指定布局的 XML 不同的 XML 资源中进行定义。
主题
主题是对整个Activity或应用而不是对单个View应用的样式。以主题形式应用样式时,Activity或者应用中的每个视图都将应用其支持的每个样式属性。
定义样式
要创建一组样式,请在您的项目的 res/values/ 目录中保存一个 XML 文件。 可任意指定该 XML 文件的名称,但它必须使用 .xml 扩展名,并且必须保存在 res/values/ 文件夹内。
该 XML 文件的根节点必须是 <resources>。
对于您想创建的每个样式,向该文件添加一个 <style> 元素,该元素带有对样式进行唯一标识的 name 属性(该属性为必需属性)。然后为该样式的每个属性添加一个 <item> 元素,该元素带有声明样式属性以及属性值的 name(该属性为必需属性)。 根据样式属性,` 的值可以是关键字字符串、十六进制颜色值、对另一资源类型的引用或其他值。以下是一个包含单个样式的示例文件:
<?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 属性中的值引用。 可从 XML 布局以 @style/CodeFont 形式引用该示例样式(如上文引言中所示)。
style 元素中的 parent 属性是可选属性,它指定应作为此样式所继承属性来源的另一样式的资源 ID。 如果愿意,您可在随后替换这些继承的样式属性。
切记,在 XML 中定义您想用作Activity或应用主题的样式与定义视图样式的方法完全相同。诸如上文所定义的样式可作为单个视图的样式加以应用,也可作为整个Activity` 或应用的主题加以应用。 后文将阐述如何为单个视图应用样式或如何以应用主题形式应用样式。
样式继承
您可以通过 <style> 元素中的 parent 属性指定应作为您的样式所继承属性来源的样式。您可以利用它来继承现有样式的属性,然后只定义您想要更改或添加的属性。 您可以从自行创建的样式或平台内建的样式继承属性。 例如,您可以继承 Android 平台的默认文本外观,然后对其进行修改:
<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 属性。
注:这种通过将名称链接起来的继承方法只适用于由您自己的资源定义的样式。 您无法通过这种方法继承 Android 内建样式。 要引用内建样式(例如 TextAppearance),您必须使用 parent 属性。
对 UI 应用样式和主题
设置样式的方法有两种:
- 如果是对单个视图应用样式,请为布局 XML 中的 View 元素添加 style 属性。
<TextView
style="@style/CodeFont"
android:text="@string/hello" />
- 或者,如果是对整个 Activity 或应用来应用样式,请为 Android 清单中的 或 元素添加 android:theme 属性。
<application android:theme="@style/CustomTheme">
<activity android:theme="@android:style/Theme.Dialog">
当您对布局中的单个View应用样式时,该样式定义的属性只应用于该 View。 如果对ViewGroup应用样式,子View元素将不会继承样式属性只有被您直接应用样式的元素才会应用其属性。 不过,您可以通过以主题形式应用样式,使所应用的样式作用于所有 View 元素。
要以主题形式应用样式定义,您必须在 Android 清单中将样式应用于 Activity 或应用。 如果您这样做,Activity 或应用内的每个 View 都将应用其支持的每个属性。 例如,如果您对某个 Activity 应用前面示例中的 CodeFont 样式,则所有支持这些文本样式属性的 View 元素也会应用这些属性。 任何不支持这些属性的 View 都会忽略这些属性。 如果某个 View 仅支持部分属性,将只应用这些属性。
根据平台版本选择主题
新版本的 Android 可为应用提供更多主题,您可能希望在这些平台上运行时可以使用这些新增主题,同时仍可兼容旧版本。 您可以通过自定义主题来实现这一目的,该主题根据平台版本利用资源选择在不同父主题之间切换。
例如,以下这个声明所对应的自定义主题就是标准的平台默认明亮主题。 它位于 res/values 之下的一个 XML 文件(通常是 res/values/styles.xml)中:
<style name="LightThemeSelector" parent="android:Theme.Light">
...
</style>
为了让该主题在应用运行在 Android 3.0(API 级别 11)或更高版本系统上时使用更新的全息主题,您可以在 res/values-v11 下的 XML 文件中加入一个替代主题声明,但将父主题设置为全息主题:
<style name="LightThemeSelector" parent="android:Theme.Holo.Light">
...
</style>
现在像您使用任何其他主题那样使用该主题,您的应用将在其运行于 Android 3.0 或更高版本的系统上时自动切换到全息主题。
@ 和?符号的引用区别
“@” 与 “?” 符号的引用在使用时都有一个规范的格式:“@[+][package:]type:name”,“?[package:][type:]name”。可以看到,二者均包含引用符号、资源所属的包、资源类型和资源名称。
@ 资源引用
” 符号用于引用系统和我们在项目中添加的一些固有资源(drawable,string 等),或者定义的 style 样式。比如:
android:text="@string/app_name"
这里的 app_name 就是我们自己定义在项目文件 values/strings.xml 中的字符串资源。
android:text="@android:string/cancel"
而这里的cancel属于Android SDK中的系统字符串资源,所以需要添加 @android: 来指明引用来源。android: 是 package:的一个具体实例。
? 属性引用
“?”符号用于引用当前主题中定义的一些属性值。
注意,“?” 符号通过属性名字间接引用当前主题中的对应属性值,而不是属性本身。
举个例子:
android:divider="?android:listDivider"
这里的 “?” 符号通过属性名 android:listDivider 间接获取当前主题赋予该属性的值。如同 @android: 一般,?android: 表示该值源自 Android SDK 系统属性。由于在当前主题中寻找对应属性名的值,所以没有指定属性类型,其实等同于:?android:attr/listDivider。
那如何引用项目中自定义的属性呢?我们在 attrs.xml 中定义一个属性,如:
<declare-styleable name="CustomTextView">
<attr name="colorTextCustom" format="reference|color"/>
</declare-styleable>
显然,此时我们定义的 colorTextCustom 属性是没有值的,直接引用没有任何作用。需要在主题 style 中赋值:
<style name="BaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorTextCustom">#FF0000</item>
</style>
<style name="AppTheme" parent="BaseTheme">
<item name="android:textColor">?colorTextCustom</item>
</style>
可以看到,这里在BaseTheme中对colorTextCustom属性赋值,并在 AppTheme中通过“?colorTextCustom” 引用该属性值。由于是本地项目中定义的属性,所以没有添加 android: 命名空间。其实,这种做法的好处是,AppTheme所覆盖的 View 均可通过构造函数获取当前主题中的 colorTextCustom 属性值。
网友评论