style和theme都是用于定义控件的显示样式,只不过style只能作用于单独的一个控件;theme虽然也是style的一种,但theme作用的是整个APP或某个界面或一组控件:如果你的theme用在清单文件的application节点下,那么这个theme就作用于整个APP;如果用在某个清单文件的activity节点下,它就只作用于这个界面。
一、创建并引用style
你的style一般定义在项目的res/values/styles.xml文件中,如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="GreenText" parent="TextAppearance.AppCompat">
<item name="android:textColor">#00FF00</item>
</style>
</resource>
在style节点中申明的是这个style的名称和其继承的父类style,item节点中申明的是要修改的控件属性名字和属性值,只要能在布局文件中定义出来的控件属性同样都可以定义在item节里。然后通过如下的形式来为一个控件引用这个style
<TextView
style="@style/GreenText"
... />
二、继承并修改系统style
上面我们知道,继承一个style,只需要在style节点中通过parent指定父类style就可以了。这里的父类style有两种来源,一种是安卓系统默认的style,另一种就是v4或v7支持包下的style,一般建议用支持包下的style,因为这些支持包下的style在4.0以上兼容性更好。以下是引用系统默认的style:
<style name="GreenText" parent="@android:style/TextAppearance">
<item name="android:textColor">#00FF00</item>
</style>
以下是引用支持包下的style:
<style name="GreenText" parent="TextAppearance.AppCompat">
<item name="android:textColor">#00FF00</item>
</style>
通过对比我们发现:系统默认的style一般都以@android:style开头,而支持包下的style一般会包含Appcompat,这就好区分了。
这里有一个小问题,如果我们自定义了自己的一个style,有时候我们需要只改动其中一项或几项属性,用于新的控件,怎样改比较优雅呢?其实除了上面的parent方式,我们还可以通过以下方式来实现:
<style name="GreenText.Large">
<item name="android:textSize">22dp</item>
</style>
其中,GreenText就是我们自定义的父类style名称,句点后的Large就是当前style的真正名称。这样,当前的style就具有了GreenText的所有样式,只不过其中的字体大小被改成了22dp。需要注意的是:这种继承方式仅仅限于继承我们自定义的样式,如果是安卓默认的样式或支持包中的样式则不能这样。另外,如果通过这样的方式继承了一个我们的自定义样式,又通过parent方式继承了新的style,那么新的style将会替换掉前者的style。例如:
<style name="GreenText.Large" parent="新的style">
<item name="android:textSize">22dp</item>
</style>
三、创建并引用theme
整个APP引用:
<manifest ... >
<!--Theme.AppCompat为夜间主题-->
<application android:theme="@style/Theme.AppCompat" ... >
</application>
</manifest>
某个activity引用:
<manifest ... >
<application ... >
<!--Theme.AppCompat.Light为日间主题-->
<activity android:theme="@style/Theme.AppCompat.Light" ... >
</activity>
</application>
</manifest>
其中,activity中的theme将会覆盖掉application中的theme对该界面的作用。其实,从android5.0和v22.1的支持包开始,theme也可以在布局文件中通过android:theme方式单独作用于一个控件的,只不过不经常这样用。
创建、继承theme的方式跟创建、继承style的方式是一样的,当我们创建了一个新的项目时,as会为我们生成一个默认的theme并在清单文件application节点中默认引用了,如下:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- colorPrimary控制的是app bar的颜色和其他主要部分的颜色 -->
<item name="colorPrimary">@color/colorPrimary</item>
<!-- colorPrimaryDark主要控制的是手机状态栏的颜色-->
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<!-- colorAccent整体控制整个APP中checkbox和radiubutton等控件选中后的默认颜色和某些文本的颜色-->
<item name="colorAccent">@color/colorAccent</item>
<!--新布局文件创建时默认的背景色-->
<item name="android:windowBackground">@color/activityBackground</item>
</style>
我们可以在上面修改想要的主题,也可以增加新的item属性,例如是否隐藏app bar等。
四、使用特定android版本的新theme
比如说你现在项目里已有一个名字为BaseAppTheme的主题,现在android5.0以上新增了某些新的主题属性,你想让你的APP运行在5.0以上的设备时能够使用这些新的主题。可以通过以下方式实现:
1、在res/values/styles.xml 文件中定义一个主题继承BaseAppTheme:
<resources>
<!-- 这是所有版本都可以使用的基础主题 -->
<style name="BaseAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryDark">@color/primaryTextColor</item>
<item name="colorAccent">@color/secondaryColor</item>
</style>
<!-- 在清单文件中引用的主题 -->
<style name="AppTheme" parent="BaseAppTheme" />
</resources>
2、新建res/values-v21/styles.xml文件并定义AppTheme主题,继承BaseAppTheme,新增主题属性。其中的v21为API版本,即只有5.0以上的系统才使用的主题属性:
<resources>
<style name="AppTheme" parent="BaseAppTheme">
<!--全局的activity切换时是否使用过渡动画-->
<item name="android:windowActivityTransitions">true</item>
<!--全局的activity进入动画-->
<item name="android:windowEnterTransition">@android:transition/slide_right</item>
<!--全局的activity退出动画-->
<item name="android:windowExitTransition">@android:transition/slide_left</item>
</style>
</resources>
五、为某种类型的控件统一全局的样式
无论是android系统中还是支持包中的每一个控件,都有一个默认的样式,例如一个Button的默认样式叫Widget.AppCompat.Button,你可以为布局文件中的某个Button单独使用该样式,例如:
<Button
style="@style/Widget.AppCompat.Button.Borderless"
... />
你也可以在APP的主题中为所有Button统一样式,例如:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="buttonStyle">@style/Widget.AppCompat.Button.Borderless</item>
...
</style>
扩展:为所有Textview统一样式可以用textAppearance属性;为所有Checkbox统一样式用checkboxStyle属性;为所有RadioButton统一样式用radioButtonStyle属性等等。这些控件属性默认都已Widget.Appcompat开头。