在写代码的时候,经常遇到自定义的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. 【转】HttpWebRequest 保持session

    通过HttpWebRequest获取网页内容并保持session,最主要的就是存储cookie.这里使用了一个静态变量m_Cookie用来存储cookie的内容.第二次请求网页的时候把cookie传送 ...

  2. OOP_由C到C++

    由C到C++ OOP第一课 C语言的局限 C++的特点 C++的程序特征 C++程序的结构特性 C++程序的编辑.编译和运行 ⭐C++对C的补充 C语言的局限 类型检查机制相对较弱,使得程序中的一些错 ...

  3. DDD中的EFCore

    EFCore在DDD中的使用 在DDD中,我们对聚合根的操作都会通过仓储去获取聚合实例. 因为聚合根中可能会含有实体属性,值对象属性,并且,在DDD中,我们所设计的领域模型都是充血模型.所以,在对聚合 ...

  4. 判断img图片是否加载成功

    上班之余,记录一下工作中遇到的有趣问题... 事情是这样的...在做一个内嵌H5的app时,有一个“个人名片”页面...要求:如果后台接口有给头像的图片链接就用他们给的,如果没给,前端给个默认头像.. ...

  5. Quartz.Net定时任务简单实用(实例)

    一.Quartz.Net是什么? Quartz.Net是一个定时任务框架 二.有Timer了,为什么需要用Quartz.Net? Quartz.Net比Timer使用起来更灵活.例如:每个月最后一个星 ...

  6. 有趣的sql

    1.操作字段 a. 添加字段 alter table CompanyRegisterOrder add CreateTime datetime not null default getdate(), ...

  7. Hibernate 学习(三)

    一.关系映射 实体类之间的关联映射以及表之间的关系是 ORM 的灵魂之处.对象间的关系的子集可以用下列四种方式解释.关联映射可以是单向的也可以是双向的.  映射类型 描述 Many-to-One 使用 ...

  8. react antd Warning: must set key for <rc-animate> children

    location 有可能是一个‘’,''.split() 将输出[""],是个含有空字符串的数组,而[]是个什么都没有的数组,两者不同. code: change initialV ...

  9. MySQL数据库(5)----删除或更新已有行

    有时候,会需要删除某些行,或者修改其内容.这是候便需要用到DELETE语句和UPDATE语句. 1. DELETE 语句的基本格式如下所示: DELETE FROM tbl_name WHERE wh ...

  10. [转]ggplot2用法简单介绍

    简介 ggplot2包是基于Wilkinson在<Grammar of Graphics>一书中所提出的图形语法的具体实现, 这套图形语法把绘图过程归纳为data, transformat ...