您的位置:首页 > 其它

手把手带你理解style

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

一、前言

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

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


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

二、为view编写style

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

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

<resourcesxmlns:android="http://schemas.android.com/apk/res/android">

<!--
Baseapplicationtheme,dependentonAPIlevel.Thisthemeisreplaced
byAppBaseThemefromres/values-vXX/styles.xmlonnewerdevices.
-->
<stylename="AppBaseTheme"parent="android:Theme.Light">
<!--
ThemecustomizationsavailableinnewerAPIlevelscangoin
res/values-vXX/styles.xml,whilecustomizationsrelatedto
backward-compatibilitycangohere.
-->
</style>

<!--Applicationtheme.-->
<stylename="AppTheme"parent="AppBaseTheme">
<!--AllcustomizationsthatareNOTspecifictoaparticularAPI-levelcangohere.-->
</style>

<stylename="MyText">
<itemname="android:text">我是自定义style</item>
<itemname="android:textSize">25sp</item>
<itemname="android:textColor">#008</item>
</style>

</resources>


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

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


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

<RelativeLayoutxmlns: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"
>

<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MyText"/>

</RelativeLayout>


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



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

(1)优先级别实验

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

<RelativeLayoutxmlns: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"
>

<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我被修改了"
style="@style/MyText"/>

</RelativeLayout>


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



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

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


(2)style也是可继承的

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

<resourcesxmlns:android="http://schemas.android.com/apk/res/android">

<!--
Baseapplicationtheme,dependentonAPIlevel.Thisthemeisreplaced
byAppBaseThemefromres/values-vXX/styles.xmlonnewerdevices.
-->
<stylename="AppBaseTheme"parent="android:Theme.Light">
<!--
ThemecustomizationsavailableinnewerAPIlevelscangoin
res/values-vXX/styles.xml,whilecustomizationsrelatedto
backward-compatibilitycangohere.
-->
</style>

<!--Applicationtheme.-->
<stylename="AppTheme"parent="AppBaseTheme">
<!--AllcustomizationsthatareNOTspecifictoaparticularAPI-levelcangohere.-->
</style>

<stylename="MyText">
<itemname="android:text">我是自定义style</item>
<itemname="android:textSize">25sp</item>
<itemname="android:textColor">#008</item>
</style>
<stylename="My"parent="@style/MyText">

</style>

</resources>


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

<RelativeLayoutxmlns: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"
>

<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/My"/>

</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,将我们的自定义属性构建出来。代码如下:

<?xmlversion="1.0"encoding="utf-8"?>
<resources>
<declare-styleablename="MyView">
<attrname="textColor"format="color"/>
<attrname="textSize"format="dimension"/>
</declare-styleable>
</resources>


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

<resourcesxmlns:android="http://schemas.android.com/apk/res/android">

<!--
Baseapplicationtheme,dependentonAPIlevel.Thisthemeisreplaced
byAppBaseThemefromres/values-vXX/styles.xmlonnewerdevices.
-->
<stylename="AppBaseTheme"parent="android:Theme.Light">
<!--
ThemecustomizationsavailableinnewerAPIlevelscangoin
res/values-vXX/styles.xml,whilecustomizationsrelatedto
backward-compatibilitycangohere.
-->
</style>

<!--Applicationtheme.-->
<stylename="AppTheme"parent="AppBaseTheme">
<!--AllcustomizationsthatareNOTspecifictoaparticularAPI-levelcangohere.-->
</style>

<stylename="mytext">
<itemname="android:text">我是自定义style</item>
<itemname="com.fuly.kun:textSize">25sp</item>
<itemname="com.fuly.kun:textColor">#008</item>
</style>

</resources>


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

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


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

<RelativeLayoutxmlns: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"
>

<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/mytext"/>

</RelativeLayout>


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



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

三、style的Theme使用

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

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

<RelativeLayoutxmlns: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里的代码,如下:

<resourcesxmlns:android="http://schemas.android.com/apk/res/android">

<!--
Baseapplicationtheme,dependentonAPIlevel.Thisthemeisreplaced
byAppBaseThemefromres/values-vXX/styles.xmlonnewerdevices.
-->
<stylename="AppBaseTheme"parent="android:Theme.Light">
<!--
ThemecustomizationsavailableinnewerAPIlevelscangoin
res/values-vXX/styles.xml,whilecustomizationsrelatedto
backward-compatibilitycangohere.
-->
</style>

<!--Applicationtheme.-->
<stylename="AppTheme"parent="AppBaseTheme">
<!--AllcustomizationsthatareNOTspecifictoaparticularAPI-levelcangohere.-->
</style>
<stylename="mytheme">
<itemname="android:windowNoTitle">true</item>
<itemname="android:textColor">#00ff00</item>
</style>

</resources>


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

<!--Windowattributes-->
<itemname="windowBackground">@android:drawable/screen_background_selector_dark</item>
<itemname="windowFrame">@null</item>
<itemname="windowNoTitle">false</item>
<itemname="windowFullscreen">false</item>
<itemname="windowOverscan">false</item>
<itemname="windowIsFloating">false</item>
<itemname="windowContentOverlay">@null</item>
<itemname="windowShowWallpaper">false</item>
<itemname="windowTitleStyle">@android:style/WindowTitle</item>
<itemname="windowTitleSize">25dip</item>
<itemname="windowTitleBackgroundStyle">@android:style/WindowTitleBackground</item>
<itemname="android:windowAnimationStyle">@android:style/Animation.Activity</item>
<itemname="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
<itemname="windowActionBar">false</item>
<itemname="windowActionModeOverlay">false</item>
<itemname="windowCloseOnTouchOutside">false</item>
<itemname="windowTranslucentStatus">false</item>
<itemname="windowTranslucentNavigation">false</item>


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

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

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

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

<?xmlversion="1.0"encoding="utf-8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="com.fuly.kun"
android:versionCode="1"
android:versionName="1.0">

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18"/>

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name="com.fuly.kun.MainActivity"
android:label="@string/app_name"
android:theme="@style/mytheme">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>

<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>

</manifest>


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



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

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

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

packagecom.fuly.kun;

importandroid.os.Bundle;
importandroid.app.Activity;
importandroid.view.Menu;

publicclassMainActivityextendsActivity{

protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setTheme(R.style.mytheme);
setContentView(R.layout.activity_main);

}

}


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



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

(1)使用继承

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

<resourcesxmlns:android="http://schemas.android.com/apk/res/android">

<!--
Baseapplicationtheme,dependentonAPIlevel.Thisthemeisreplaced
byAppBaseThemefromres/values-vXX/styles.xmlonnewerdevices.
-->
<stylename="AppBaseTheme"parent="android:Theme.Light">
<!--
ThemecustomizationsavailableinnewerAPIlevelscangoin
res/values-vXX/styles.xml,whilecustomizationsrelatedto
backward-compatibilitycangohere.
-->
</style>

<!--Applicationtheme.-->
<stylename="AppTheme"parent="AppBaseTheme">
<!--AllcustomizationsthatareNOTspecifictoaparticularAPI-levelcangohere.-->
</style>
<stylename="mytheme"parent="@android:style/Theme.Dialog">
<itemname="android:windowNoTitle">true</item>
<itemname="android:textColor">#00ff00</item>
</style>

</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"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: