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

一、前言

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

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

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

二、为view编写style

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

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

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

     <!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style> <!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style> <style name="MyText">
<item name ="android:text">我是自定义style</item>
<item name="android:textSize">25sp</item>
<item name="android:textColor">#008</item>
</style> </resources>

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

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

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

 <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"
> <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中的代码修改如下:

 <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"
> <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中的代码如下:

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

     <!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style> <!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style> <style name="MyText">
<item name ="android:text">我是自定义style</item>
<item name="android:textSize">25sp</item>
<item name="android:textColor">#008</item>
</style>
<style name="My" parent="@style/MyText"> </style> </resources>

在代码的第25行,新建了一个style,名字为My,它继承了MyText。但是它自己却是什么都没有添加。现在我们来使用这个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"
> <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,将我们的自定义属性构建出来。代码如下:

 <?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyView">
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
</declare-styleable>
</resources>

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

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

     <!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style> <!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style> <style name="mytext">
<item name ="android:text">我是自定义style</item>
<item name="com.fuly.kun:textSize">25sp</item>
<item name="com.fuly.kun:textColor">#008</item>
</style> </resources>

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

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

好了,剩下的与上面的使用一样,为了让你看的明白。我就把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"
> <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语句。如下:

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

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

     <!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style> <!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
<style name="mytheme">
<item name="android:windowNoTitle">true</item>
<item name="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源码关联,没关系,我把我找到的贴出来给你看,如下:

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

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

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

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

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

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns: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>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

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

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

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

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

 package com.fuly.kun;

 import android.os.Bundle;
import android.app.Activity;
import android.view.Menu; public class MainActivity extends Activity { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.mytheme);
setContentView(R.layout.activity_main); } }

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

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

(1)使用继承

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

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

     <!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style> <!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
<style name="mytheme" parent="@android:style/Theme.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="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"

手把手带你理解style的更多相关文章

  1. [转帖]从零开始入门 K8s | 手把手带你理解 etcd

    从零开始入门 K8s | 手把手带你理解 etcd https://zhuanlan.zhihu.com/p/96721097 导读:etcd 是用于共享配置和服务发现的分布式.一致性的 KV 存储系 ...

  2. 从零开始入门 K8s | 手把手带你理解 etcd

    作者 | 曾凡松(逐灵) 阿里云容器平台高级技术专家 本文整理自<CNCF x Alibaba 云原生技术公开课>第 16 讲. 导读:etcd 是用于共享配置和服务发现的分布式.一致性的 ...

  3. 手把手带你做一个超炫酷loading成功动画view Android自定义view

    写在前面: 本篇可能是手把手自定义view系列最后一篇了,实际上我也是一周前才开始真正接触自定义view,通过这一周的练习,基本上已经熟练自定义view,能够应对一般的view需要,那么就以本篇来结尾 ...

  4. 手把手带你阅读Mybatis源码(三)缓存篇

    前言 大家好,这一篇文章是MyBatis系列的最后一篇文章,前面两篇文章:手把手带你阅读Mybatis源码(一)构造篇 和 手把手带你阅读Mybatis源码(二)执行篇,主要说明了MyBatis是如何 ...

  5. Java开发不懂Docker,学尽Java也枉然,阿里P8架构师手把手带你玩转Docker实战

    转: Java开发不懂Docker,学尽Java也枉然,阿里P8架构师手把手带你玩转Docker实战 Docker简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一 ...

  6. HashMap源码深度剖析,手把手带你分析每一行代码,包会!!!

    HashMap源码深度剖析,手把手带你分析每一行代码! 在前面的两篇文章哈希表的原理和200行代码带你写自己的HashMap(如果你阅读这篇文章感觉有点困难,可以先阅读这两篇文章)当中我们仔细谈到了哈 ...

  7. [.Net] 手把手带你将自己打造的类库丢到 NuGet 上

    手把手带你将自己打造的类库丢到 NuGet 上 序 我们习惯了对项目右键点击“引用”,选择“管理NuGet 程序包”来下载第三方的类库,可曾想过有一天将自己的打造的类库放到 NuGet 上,让第三者下 ...

  8. 一个故事带你理解if __name__ == '__main__'

    如果你刚刚接触python,相信会在看别人的程序的时候会遇到if __name__ == '__main__'酱紫的语法,如果当时没看懂现在也一知半解的话,看下去,本文可以帮你解决这个问题. 大家都知 ...

  9. Android性能优化:手把手带你全面实现内存优化

      前言 在 Android开发中,性能优化策略十分重要 本文主要讲解性能优化中的内存优化,希望你们会喜欢 目录   1. 定义 优化处理 应用程序的内存使用.空间占用 2. 作用 避免因不正确使用内 ...

随机推荐

  1. bzoj 4709: [Jsoi2011]柠檬

    Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有 N (1 ≤ N ≤ 100,000) 只,按顺序串在树枝上.为了方便,我们从 ...

  2. Firebird 列可空非空修改

    2018-12-04 至少到Firebird 3.0.4 已经添加了设置可空 和 非空的语法:如 -- 删除非空(设置为可空) ALTER TABLE TECH ALTER label drop NO ...

  3. ReSharper+Devexpress 删除光标之后的换行

    echo. >"$(ProjectDir)\Properties\licenses.licx" 官方链接

  4. Lakeshore用户手册

    1.场景 场景是游戏的基本组成部分,开始界面,结束界面,每个关卡都是一个场景.游戏中基于游戏的情节,可以在各个场景间跳转. 2.精灵 精灵可以理解为图片的容器.如果需要在游戏场景中插入一个静态图片,那 ...

  5. sql server分页查询

    1.引言 在列表查询时由于数据量非常多,一次性查出来会非常慢,就算一次查出来了,也不能一次性显示给客户端,所以要把数据进行分批查询出来,每页显示一定量的数据,这就是数据要分页. 2.常用的数据分页方法 ...

  6. Node.js学习笔记(六) --- Nodejs 的非阻塞 I/O、 异步、 事件驱动

    1. Nodejs 的单线程 非阻塞 I/O 事件驱动在 Java. PHP 或者.net 等服务器端语言中,会为每一个客户端连接创建一个新的线程.而每个线程需要耗费大约 2MB 内存.也就是说,理论 ...

  7. Java温故而知新(3)异常处理机制

    异常处理是程序设计中一个非常重要的方面,也是程序设计的一大难点,从C开始,你也许已经知道如何用if...else...来控制异常了,也许是自发的,然而这种控制异常痛苦,同一个异常或者错误如果多个地方出 ...

  8. hdu 4628 Pieces 状态压缩dp

    Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total S ...

  9. 中南oj 1216: 异或最大值 数据结构

    1216: 异或最大值 Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 98  Solved: 29 [Submit][Status][Web Boar ...

  10. flask 服务器详解

    #!/usr/local/bin/python # coding=utf-8 from flask import Flask app = Flask(__name__) @app.route('/') ...