Android - Attr、Style、Theme浅析
2016-10-31 21:35
369 查看
Android - Attr、Style、Theme浅析
——念念不往,坚持你所坚持的。
学习Android也将近有一年多的时间了。在这一年里,从一个什么都不懂的小白,逐渐转变成为一个初级开发者,其中发生了许许多多的事情。这个世上有太多的事情,放在你面前的时候,你不知所措。不知从何下手,不知道自己是否可以做的来。但是,相信都不会去拒绝去尝试它。但是,能够坚持下来的真的是一件了不起的事情。
从开始从入门到查阅资料,阅读博客,阅读订阅号分享,和技术大牛交流。慢慢的开始自己写博客,自己写demo,参加比赛,去公司实习,回实验室带队。这一切经历都不断的使自己变得更加强壮并生长起来,就像一个破土而出的嫩苗,强劲而又充满希望。念念不忘,坚持你所坚持的。
前言
自己在做demo的时候,在网上查阅了一些相关的介绍和用法,并把它在自己的demo中应用。感觉Style、Attr、Theme这三个概念还是非常重要的,尤其对于一些初级开发者来说。它贯穿Android框架的方方面面,是Android设计的重要一环,深入理解其中的用法对于将后的开发会有深远的意义。说明
本文有部分参照【简书_作者:CPPAlien】Attr、Style和Theme详解,阅读原文请移步这里。概念说明
Attr:属性,风格样式的最小单元;Style:风格,它是一系列Attr的集合用以定义一个View的样式,比如height、width、padding等;
Theme:主题,它与Style作用一样,不同于Style作用于个一个单独View,而它是作用于Activity上或是整个应用。
Attr的定义
我们可以先哪一个TextView的例子来举例,介绍一下如何在Android中定义一个Attr,比如下面这个简单的TextView:
其中layout_width对应到框架中的attr信息如下:
<declare-styleable name="ViewGroup_Layout"> <attr name="layout_width" format="dimension"> <enum name="fill_parent" value="-1" /> <enum name="match_parent" value="-1" /> <enum name="wrap_content" value="-2" /> </attr> ... </declare-styleable>
从上可以看到layout_width可以使用三个枚举值,并且其中fill_parent和match_parent的value值都为-1。我们知道,从2.2开始Android框架就推荐用match_parent代替fill_parent,而以上代码为了实现了兼容,因为它们对应的值都为-1。
以上的textStyle的属性信息在源码中如下:
<attr name="textStyle"> <flag name="normal" value="0" /> <flag name="bold" value="1" /> <flag name="italic" value="2" /> </attr>
它也对应了三个值,但这里却使用了flag标签。这里我们应该理解flag与enum的差别:flag表示这几个值可以做或运算,比如上面的textStyle,你可以叠加使用,如用bold|italic表示既加粗也变成斜体,而enum只能让你选择其中一个值。
看完上例后,我们来试着自己自定义一个自己的属性,在values目录下创建一个attrs.xml文件,在元素里面首先申明一个自己的表示一个属性组,再在里面加上属性就行。如下我们定义一个DemoStyle的属性组,其中有三个属性一个是DemoName,一个是DemoType,DemoName的格式我们设置为string,最后一个是DemoColor,这样一个属于我们自己的属性就定义成功了。
attr的format根据字面意思也挺容易理解的,这里我解释下reference的用法。它用在一些可以设置引用值的情况,比如@drawable/myImage、@color/myColor等。当然format也可以进行或运算,一般我们定义color类型的属性时,也一般会把format写成format=”reference|color”,这样我们不但可以设置颜色值,如#FFFFFF,还可以使用我们自己定义的demo图片,如@drawable/demo_pic。
TIPS:format即使用错,只要你自定义的View中获取对应类型值也是可以的,只是在布局中写代码时,IDE就不会根据你定义的format给出相应的提示了,所以最好在自定义View时还是仔细斟酌下类型。
Style的使用
如下我们在styles.xml中定义一个Demo风格<style name="SchnauzerStyle"> <item name="DemoName">Demo</item> <item name="DemoColor">@drawable/demo_color</item> <item name="DemoType">Normal</item> </style>
下面我们看下如何让一个Style作用在一个View上的。
首先我们自定义了一个View命名为DemoView,然后创建一个布局文件中加入该DemoView视图,并让该View使用SchnauzerStyle风格。代码如下:
<cn.hadcn.test.DemoView style="@style/Demo" android:layout_height="wrap_content" android:layout_width="wrap_content"/>
移步到DemoView的Java代码中,我们可以通过theme的obtainStyledAttributes方法来获得我们刚刚定义的几个Attr属性在Style中的内容,如下我们举一个获得DmoeName的例子:
final Resources.Theme theme = context.getTheme(); TypedArray demoArray = theme.obtainStyledAttributes(attrs, R.styleable.DemoStyle, defStyleAttr, defStyleRes); String name = demoArray.getString(R.styleable.DemoStyle_DemoName); Log.e("Demo", "name = " + name); demoArray.recycle();
以上obtainStyledAttributes有四个入参,前两个比较容易理解,后两个用作指定默认的Style,表示如果attrs中没有你想获得的属性,但如果你指定了默认Style,它会去从该默认的Style里面找你想要的属性。defStyleAttr和defStyleRes功能一样,指定的资源形式不同,前者表示一个默认的指向一个style风格的attr属性,而后者你可以直接传入一个style风格的id。注意以上定义的Style只能在这个DemoView中被使用,如果你想在其他View使用,就需要再在需要使用的View中增加这个Style。这就是先前我们说的Style只能作用于一个View。
Theme的使用
Theme与Style使用同一个元素标签<activity android:name=".MainActivity" android:theme="@style/DemoStyle"> ...
以上理论上是可行的,不过运行后,程序却出现奔溃,出现以下错误提示:
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
有些同学一眼可能就看出,因为在这里Activity或Application的需要很多属性才能工作的,而此处我们只给它传一个DemoStyle,这当然不行,所以我们需要对这个Style做下处理,让DemoStyle继承一个系统主题,如下:
<style name="DemoStyle" parent="Theme.AppCompat"> <item name="DemoName">Demo</item> <item name="DemoColor">@drawable/demo</item> <item name="DemoType">Normal</item> </style>
这样一个Demo主题就诞生了,而在这个Activity下的所有View都可以用Demo的信息了。Application中定义theme的原理一样,这里就不多说了。
TIPS:框架使用Attr的顺序是:View中的Style会优先于Activity中的Theme,Activity中的Theme会优先于Application中的Theme,所以说你可以定义整个应用的总体风格,但局部风格你也可以做出自己的调整。
Attr的获得方法
有些情况下,我们可能需要使用theme中的属性值,比如下面我们想让一个TextView直接显示DemoName这个属性的内容,并且使用系统字体的颜色,则可以如下做:<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="?android:textColorDemo" android:text="?attr/DemoName"/>
获得一个Attr的方法,不同于普通资源使用@符号获得的方式,而是需要使用?符号来获得属性,整体的表达方式如下:
?[*<package_name>*:][*<resource_type>*/]*<resource_name>*
如果是本应用中的attr使用,则可以省去部分。
此处的textColor使用当前主题的android:textColorDemo属性内容。因为资源工具知道此处是一个属性,所以省去了attr (完整写法:?android:attr/textColorDemo)。
总结
我刚开始学Android的时候,也总对这三个概念很迷惑,不知道什么是属性,什么是风格,什么是主题,它们之间又有什么关系?它们在Android框架中又充当什么角色?又如何自己去定义?但随着学习的深入,越发觉得这三块内容真是Android框架的一大神器,有时你不用改动代码,只要换一个theme,应用马上焕发青春。而且也尝试用所学内容去写自己的theme,不但可以让自己的布局文件更加清晰明了,而且还让自己的代码具有更高的扩展性,真是好处多多,希望对这块还不了解的童鞋多多研习。相关文章推荐
- Android中的style,attr,theme
- 读 << Android开发之Theme、Style探索及源码浅析 >> 一文记录下
- Android中的style,attr,theme
- Android中的style,attr,theme
- [Android基础]theme、style、attr之间联系与区别
- Android中的style,attr,theme
- Android开发之Theme、Style探索及源码浅析
- 【Android】attr、style和theme
- android风格和主题程序编写–style & theme
- android全屏设置代码:android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
- Android中Style和Theme的使用
- android的样式(style)与主题(theme)
- Android中的样式和主题(style & theme)
- android基础---样式和主题(style&theme)
- Android基础之Style Theme
- android (style&theme)
- 深入理解android style theme(转自eoe)
- Android 学习《Theme与style》
- Android入门第十六篇之Style与Theme
- Android中Theme和Style的应用