在写代码的时候,经常遇到自定义的style,有的用来设置属性,有的用来设置主题,搞的自己云里雾里,因此在心底暗暗发誓,等到空闲的时候,一定好好学学android中的style的究竟是个什么东西,到底有什么用处。于是今天来了机会,到网上学习了一个别人写的相关的文章。虽然有的地方还是有些不太懂,但是起码算是对style有了一个初步的理解和使用。在此,特别记录下自己的学习收获,好记性不如烂笔头。由于本人是初学者,文中如果有不合理的地方,恳请大家批评指正。android进阶的道路上,一起坚持学习!

一、前言

     android中的style设计,其实主要是程序开发者来自定义一种自己需要的样式,或者叫风格。它应用主要分为两个方面

(1)Theme,即自定义主题,这是针对窗体级别的,给一个窗体设计一个风格或者叫样式。
(2)属性等的设置,这主要是针对窗体元素级别的,比如给一个view或者布局设定样式。

      另一方面,由于style天生就可以集成属性,因此它的另一个用途是也可以减少代码的复用。比如如果你的app中所有的文字都必须设定相同的大小,和相同的颜色,那么在具有文字的控件上,你不必一一为他们设定这些属性,可以将要设置的大小和颜色集成到style文件里,然后引用即可。如果你是第一次系统的了解style,可能这些话你还不是很理解,没关系接着往下看就可以了。因为不看实际的代码,是很难将这些细节性的东西说清楚的。下面就是一些实际例子,希望读者可以跟我一起编写。

 

二、为view编写style

      下面我们就来编写一个极为简单的例子来看看怎么给一个TextView自定义style。

       新建一个项目,在res/values文件夹下,建立文件styles.xml。编写其中的代码如下:

 1 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 2 
 3     <!--
 4         Base application theme, dependent on API level. This theme is replaced
 5         by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
 6     -->
 7     <style name="AppBaseTheme" parent="android:Theme.Light">
 8         <!--
 9             Theme customizations available in newer API levels can go in
10             res/values-vXX/styles.xml, while customizations related to
11             backward-compatibility can go here.
12         -->
13     </style>
14 
15     <!-- Application theme. -->
16     <style name="AppTheme" parent="AppBaseTheme">
17         <!-- All customizations that are NOT specific to a particular API-level can go here. -->
18     </style>
19     
20     <style name="MyText">
21      <item name ="android:text">我是自定义style</item>
22      <item name="android:textSize">25sp</item>
23      <item name="android:textColor">#008</item>
24     </style>
25 
26 </resources>

 

      注意,绿色背景的部分,即第20行到23行是我们新写的一个style。可以看到,在这个样式中,我们将文本大小指定为25sp,恩本的颜色指定为#008。需要说明的是

(1)MyText是我们定义的这个样式的名称,它是可以任意命名的。
(2)item标签里的name,等号里内容是控件所带的属性,即attr。一般使用的都是控件自带的。当然也可以使用你给控件自定义的attr,但这是后话。

      这个样式我们已经定义好了,下面我们在activity_main.xml中添加一个TextView控件,就可以给这个控件指定我们指定的样式了。如下:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5       >
 6 
 7     <TextView
 8         android:id="@+id/tv"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
12         style="@style/MyText"/>
13 
14 </RelativeLayout>

      代码是不是很简单,这样子,只需要第12行一句话,就同时指定了文本的大小和颜色,而且还设置了文本。MainActivity中已经自动加载了这个布局。我们运行一下,效果如下:

      怎么样,是不是对style的使用有一点感觉了呢?当然了,还有一些琐碎的知识,下面来讲。

(1)优先级别实验

      比如我们虽然在定义的样式中,设定了文本,但是如果我们在xml中,重复给TextView设置文本了呢?现将activity_main.xml中的代码修改如下:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5       >
 6 
 7     <TextView
 8         android:id="@+id/tv"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:text="我被修改了"
12         style="@style/MyText"/>
13 
14 </RelativeLayout>

      可以看到,第11行,我们给TextView指定了另外一个文本。现在运行程序,效果如下:

      文本信息显示的是我们所修改的文本,而不是style里指定的文本。其他的我就不再实验了。结论就是

在使用style的时候,已经设定的属性的级别比style指定的要高,如果发生重复,以已经设定的为准

(2)style也是可继承的

      style也是可以继承,使用parent来指定它的父style是哪一个。比如我们修改styles.xml中的代码如下:

 1 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 2 
 3     <!--
 4         Base application theme, dependent on API level. This theme is replaced
 5         by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
 6     -->
 7     <style name="AppBaseTheme" parent="android:Theme.Light">
 8         <!--
 9             Theme customizations available in newer API levels can go in
10             res/values-vXX/styles.xml, while customizations related to
11             backward-compatibility can go here.
12         -->
13     </style>
14 
15     <!-- Application theme. -->
16     <style name="AppTheme" parent="AppBaseTheme">
17         <!-- All customizations that are NOT specific to a particular API-level can go here. -->
18     </style>
19     
20     <style name="MyText">
21      <item name ="android:text">我是自定义style</item>
22      <item name="android:textSize">25sp</item>
23      <item name="android:textColor">#008</item>
24     </style>
25     <style name="My" parent="@style/MyText">
26      
27     </style>
28 
29 </resources>

       在代码的第25行,新建了一个style,名字为My,它继承了MyText。但是它自己却是什么都没有添加。现在我们来使用这个style来看看。修改activity_main.xml,如下:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5       >
 6 
 7     <TextView
 8         android:id="@+id/tv"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         style="@style/My"/>
12 
13 </RelativeLayout>

      可以看到我们这里使用了名称为My的这个style。然后运行程序,效果如下:

       跟使用MyText的style是一样的效果。因此继承会保留父style的风格,同时也会有自己的风格。

(3)style中使用自定义的attr

      关于自定义的attr,如果你不了解,可以参看我的上一篇文章:http://www.cnblogs.com/fuly550871915/p/4907048.html

     前面我们说过,style的item标签中的name字段就是控件所带的属性名称。一般都是使用android系统自带的属性。但是我们也知道,attr也是可以自定义的。那么如果我们有自定义的attr,怎么集成到style中呢?其实也很简单。依旧以上面的代码为基础。继续讲解这个例子。

      首先在values下建立attrs.xml,将我们的自定义属性构建出来。代码如下:

1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3     <declare-styleable name="MyView">  
4         <attr name="textColor" format="color" />  
5         <attr name="textSize" format="dimension" />  
6     </declare-styleable>  
7 </resources>

      从代码中看到,我们自定义了自己的属性textColor和textSize。下面我们为TextView设定样式,使用的就是我们自定义的属性。styles.xml的代码修改如下:

 1 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 2 
 3     <!--
 4         Base application theme, dependent on API level. This theme is replaced
 5         by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
 6     -->
 7     <style name="AppBaseTheme" parent="android:Theme.Light">
 8         <!--
 9             Theme customizations available in newer API levels can go in
10             res/values-vXX/styles.xml, while customizations related to
11             backward-compatibility can go here.
12         -->
13     </style>
14 
15     <!-- Application theme. -->
16     <style name="AppTheme" parent="AppBaseTheme">
17         <!-- All customizations that are NOT specific to a particular API-level can go here. -->
18     </style>
19     
20    
21      <style name="mytext">
22      <item name ="android:text">我是自定义style</item>
23      <item name="com.fuly.kun:textSize">25sp</item>
24      <item name="com.fuly.kun:textColor">#008</item>
25     </style>
26 
27 </resources>

       从绿色的代码,我们发现其实将自定义的attr集成到style中,十分简单。只需:

name中的内容改成完整的包名,然后挂上我们自定义的属性即可。比如这个样式是给TextView定义的,那么这里的包名应该就是TextView所在的那个包。

      好了,剩下的与上面的使用一样,为了让你看的明白。我就把activity_main.xml中的代码也贴出来吧,如下:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5       >
 6 
 7     <TextView
 8         android:id="@+id/tv"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         style="@style/mytext"/>
12 
13 </RelativeLayout>

       然后运行程序,效果如下:

 

好了,相信通过上面的讲解,你对style的这方面使用已经有一定的理解了吧。其实style使用很灵活,只要我们的view或者布局,带有什么属性,它就可以集成什么属性,从而设定成风格。

 

三、style的Theme使用

      在这一部分,来说一说style用来设置主题。这其实跟style来设计view的风格是一样的,唯一的区别就是item中的内容应该写成与主题相关的语句而已。你也可以继承一个style设计好的主题或者是系统自带的主题,然后来修改它。下面我们来看一个小例子吧。

      新建一个项目,然后直接修改它的activity_main.xml语句。如下:

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="我是自定义的主题" />

</RelativeLayout>

 

      代码太简单了,什么都没改,只是将TextView的文本信息改为了“我是自定义的主题”而已。然后修改styles.xml里的代码,如下:

 1 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 2 
 3     <!--
 4         Base application theme, dependent on API level. This theme is replaced
 5         by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
 6     -->
 7     <style name="AppBaseTheme" parent="android:Theme.Light">
 8         <!--
 9             Theme customizations available in newer API levels can go in
10             res/values-vXX/styles.xml, while customizations related to
11             backward-compatibility can go here.
12         -->
13     </style>
14 
15     <!-- Application theme. -->
16     <style name="AppTheme" parent="AppBaseTheme">
17         <!-- All customizations that are NOT specific to a particular API-level can go here. -->
18     </style>
19     <style name="mytheme">
20         <item name="android:windowNoTitle">true</item>
21         <item name="android:textColor">#00ff00</item>
22     </style>
23 
24 </resources>

      绿色背景的部分是我自定义了一个主题,该主题隐藏窗口标题栏,且给文字设置了颜色。你可能会郁闷,我是怎么知道wndowNoTitle这个窗体属性的呢??其实很简单,这是android系统自带的Theme.xml文件,我们只要查看它就可以发现它的主题里都有什么属性了。上面的代码的第7行,不是有parent="android:Theme.Light"这句话嘛,我们按住ctrl建,然后鼠标点击Theme就可以在eclipse中查看Theme.xml的源代码了(前提是你的eclipse与android源码先关联起来)。然后在Theme.xml中,就可以找到窗体的属性了。如果你的elipse没有与android源码关联,没关系,我把我找到的贴出来给你看,如下:

 1  <!-- Window attributes -->
 2         <item name="windowBackground">@android:drawable/screen_background_selector_dark</item>
 3         <item name="windowFrame">@null</item>
 4         <item name="windowNoTitle">false</item>
 5         <item name="windowFullscreen">false</item>
 6         <item name="windowOverscan">false</item>
 7         <item name="windowIsFloating">false</item>
 8         <item name="windowContentOverlay">@null</item>
 9         <item name="windowShowWallpaper">false</item>
10         <item name="windowTitleStyle">@android:style/WindowTitle</item>
11         <item name="windowTitleSize">25dip</item>
12         <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground</item>
13         <item name="android:windowAnimationStyle">@android:style/Animation.Activity</item>
14         <item name="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
15         <item name="windowActionBar">false</item>
16         <item name="windowActionModeOverlay">false</item>
17         <item name="windowCloseOnTouchOutside">false</item>
18         <item name="windowTranslucentStatus">false</item>
19         <item name="windowTranslucentNavigation">false</item>

      通过上面的源代码我们就可以编辑其他的窗体属性了。

     那么怎么使用这个主题呢?有两种方式。

    第一种,在Manifest.xml文件中使用

      如果我们嵌在application标签下,则整个app都是这个主题。如果嵌在某个活动下,则只有这个后动是这个主题。在这里我们嵌在活动中,修改Manifest.xml中的代码如下。为了让你看的清楚,我还是贴出完整代码吧,尽管修改的只有一句:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.fuly.kun"
 4     android:versionCode="1"
 5     android:versionName="1.0" >
 6 
 7     <uses-sdk
 8         android:minSdkVersion="8"
 9         android:targetSdkVersion="18" />
10 
11     <application
12         android:allowBackup="true"
13         android:icon="@drawable/ic_launcher"
14         android:label="@string/app_name"
15         android:theme="@style/AppTheme" >
16         <activity
17             android:name="com.fuly.kun.MainActivity"
18             android:label="@string/app_name"
19             android:theme="@style/mytheme" >
20             <intent-filter>
21                 <action android:name="android.intent.action.MAIN" />
22 
23                 <category android:name="android.intent.category.LAUNCHER" />
24             </intent-filter>
25         </activity>
26     </application>
27 
28 </manifest>

      代码第19行绿色部分,我们给MainActivity这个活动指定为我们自定义的主题了。下面运行程序,效果如下:

     我们看,确实自定义的主题生效了,没有标题栏目,且字体颜色为绿色。

     第二种:在代码中指定主题。

      我们抹去上面的修改,在MainActivity中修改如下:

 1 package com.fuly.kun;
 2 
 3 import android.os.Bundle;
 4 import android.app.Activity;
 5 import android.view.Menu;
 6 
 7 public class MainActivity extends Activity {
 8 
 9     
10     protected void onCreate(Bundle savedInstanceState) {
11         super.onCreate(savedInstanceState);
12         setTheme(R.style.mytheme);
13         setContentView(R.layout.activity_main);
14         
15     }
16 
17 
18     
19 }

       代码也很简单,在第12行,使用一句setTheme方法来设置我们的主题即可,但是注意,必须要在setContentView执行之前设置。然后运行程序,效果图如下:

 

      这里和前面有一个细微的差别,就是背景变成了白色。我也不知道这是为什么,应该是和view的绘制流程有关吧?至于我们自定义的主题效果,都达到了。

 

(1)使用继承

         我们接着上面的代码往下写。来做一个继承的实验。一切都不变,即还是在MainActivity中使用我们自定义的主题,但是我们自定义的主题要修改如下,即修改styles.xml如下:

 

 1 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 2 
 3     <!--
 4         Base application theme, dependent on API level. This theme is replaced
 5         by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
 6     -->
 7     <style name="AppBaseTheme" parent="android:Theme.Light">
 8         <!--
 9             Theme customizations available in newer API levels can go in
10             res/values-vXX/styles.xml, while customizations related to
11             backward-compatibility can go here.
12         -->
13     </style>
14 
15     <!-- Application theme. -->
16     <style name="AppTheme" parent="AppBaseTheme">
17         <!-- All customizations that are NOT specific to a particular API-level can go here. -->
18     </style>
19     <style name="mytheme" parent="@android:style/Theme.Dialog">
20         <item name="android:windowNoTitle">true</item>
21         <item name="android:textColor">#00ff00</item>
22     </style>
23 
24 </resources>

       我们只是修改了第19行,让这个主题继承自系统自带的一个主题而已。继承的是对话框。然后我们运行程序,效果图如下:

       自定义主题的效果生效了,活动变成了一个对话框,且没有标题,字体颜色也是我们设定的。可见使用继承,是十分便利的。

(2)使用系统自带的主题

     使用系统自带主题,具体的实验我就不做了。相应的使用方式也有上面两种,你要么在manifest.xml文件中指定,要么在代码中指定。但是要记住:

在xml文件中,使用系统自带主题,要使用语句:
android:theme="@android:style/Theme.Dialog"
style/后面的内容你可以更改为系统自带的其他主题

如果使用自己自定义的,只需要@style即可:
android:theme="@style/CustomTheme"
 

    下面总结一下,常用的android自带的主题:

 

android中自带的主题(theme)的集锦:
•android:theme="@android:style/Theme.Dialog"   将一个Activity显示为对话框模式
•android:theme="@android:style/Theme.NoTitleBar"  不显示应用程序标题栏
•android:theme="@android:style/Theme.NoTitleBar.Fullscreen"  不显示应用程序标题栏,并全屏
•android:theme="@android:style/Theme.Light"  背景为白色
•android:theme="@android:style/Theme.Light.NoTitleBar"  白色背景并无标题栏
•android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen"  白色背景,无标题栏,全屏
•android:theme="@android:style/Theme.Black"  背景黑色
•android:theme="@android:style/Theme.Black.NoTitleBar"  黑色背景并无标题栏
•android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"    黑色背景,无标题栏,全屏
•android:theme="@android:style/Theme.Wallpaper"  用系统桌面为应用程序背景
•android:theme="@android:style/Theme.Wallpaper.NoTitleBar"  用系统桌面为应用程序背景,且无标题栏
•android:theme="@android:style/Theme.Wallpaper.NoTitleBar.Fullscreen"  用系统桌面为应用程序背景,无标题栏,全屏
•android:theme="@android:style/Translucent" 半透明效果
•android:theme="@android:style/Theme.Translucent.NoTitleBar"  半透明并无标题栏
•android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"  半透明效果,无标题栏,全屏
•android:theme="@android:style/Theme.Panel"
•android:theme="@android:style/Theme.Light.Panel"

 

posted on 2015-10-24 21:04  fuly  阅读(577)  评论(0编辑  收藏  举报