[学习总结]8、android 自定义控件 使用declare-styleable进行配置属性(源码角度)
declare-styleable:declare-styleable是给自定义控件添加自定义属性用的。
官方的相关内部控件的配置属性文档:http://developer.android.com/reference/android/R.styleable.html
起初,在自定义控件的时候,会要求构造3个方法中的一个或多个,好比我自定义的控件PersonView,
1 public PersonView(Context context) {
2 super(context);
3 // TODO Auto-generated constructor stub
4 }
5
6 public PersonView(Context context, AttributeSet attrs, int defStyle) {
7 super(context, attrs, defStyle);
8 // TODO Auto-generated constructor stub
9 }
10
11 public PersonView(Context context, AttributeSet attrs) {
12 super(context, attrs);
13 }
其中的AttributeSet attrs一般都没给它配置和使用,所以不知道这个东西到底怎么用,后来查看源码发现,这个配置在默认情况下使用的是系统自己的默认配置,一旦你直接设定了它的属性,默认属性就会被你的赋值所替代。
下面我们拿TextView的源码看看AttributeSet是如何进行操作的。
初始化时候,在布局文件中写android:text="拉拉";

初始化TextView的时候,它的类中的属性都会初始化;

接着往下看,你可以看到以下代码:
1 TypedArray a = theme.obtainStyledAttributes(
2 attrs, com.android.internal.R.styleable.TextViewAppearance, defStyle, 0);
3 TypedArray appearance = null;
4 int ap = a.getResourceId(
5 com.android.internal.R.styleable.TextViewAppearance_textAppearance, -1);
6 a.recycle();
7 if (ap != -1) {
8 appearance = theme.obtainStyledAttributes(
9 ap, com.android.internal.R.styleable.TextAppearance);
这个就是系统在默认的资源文件R.styleable中去获取相关的配置。
如果appearance不为空,它就会去寻找获取相关属性,接着往下看。

此时的text = ""; 就是准备输出的字符串初始化。
之后它便会查找你布局文件XML中是否设定给了它text属性值
之前我们设定过android:text="拉拉"; 所以它便会得到相关的赋值,之后调用
1 setText(text, bufferType);
2 if (hint != null) setHint(hint);
输出该字符串。当资源检查赋值完毕后,调用a.recycle();释放。
同理也可以发现,像hint,textcolor这类属性都是这么初始化赋值的。
思路:
自定义控件并且自定义属性的情况下,你可以通过这样去获取判断是否配置了相关的属性,并进行赋值操作。
从源码那边我们大体知道了一个控件的属性配置和初始化流程,下面就让我们按照这个思路去自己学习下如何自定义配置。
下面我要写一个继承了TextView的PersonView类,给它设定属性配置,之后实现属性的显示。
1.首先,先写attrs.xml
在res-vlaues文件夹下创建资源文件attrs.xml或则自定义一个资源文件xx.xml,都可以。
之后在里面配置declare-styleable ,name为PersonAttr
1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3 <declare-styleable name="PersonAttr">
4 <attr name="name" format="reference" />
5 <attr name="sex" format="reference" />
6 <attr name="age" format="integer" />
7 <attr name="weight">
8 <flag name="fat" value="2" />
9 <flag name="mid" value="1" />
10 <flag name="thin" value="0" />
11 </attr>
12 <attr name="adult" format="boolean" />
13 <attr name="textSize" format="dimension" />
14 </declare-styleable>
15 </resources>
我这里设置了姓名name,性别sex,年龄age,以及特征属性weight(fat,mid,thin内部的3个属性及对应的属性值),还有是否成年adult,和TextView的字体大小textView。
可能这里有人会问,format是什么,里面的单词代表的又是什么意思。
format就是格式,里面的就是这个属性对应的格式,下面列出来大致的格式有:
1. reference:参考某一资源ID,以此类推
(1)属性定义:
<declare-styleable name = "名称">
<attr name = "background" format = "reference" />
</declare-styleable>
(2)属性使用:
<ImageView
android:layout_width = "42dip"
android:layout_height = "42dip"
android:background = "@drawable/图片ID"
/>
2. color:颜色值
<declare-styleable name = "名称">
<attr name = "textColor" format = "color" />
</declare-styleable>
3. boolean:布尔值
<declare-styleable name = "名称">
<attr name = "focusable" format = "boolean" />
</declare-styleable>
4. dimension:尺寸值。注意,这里如果是dp那就会做像素转换
<declare-styleable name = "名称">
<attr name = "layout_width" format = "dimension" />
</declare-styleable>
5. float:浮点值。
6. integer:整型值。
7. string:字符串
8. fraction:百分数。
9. enum:枚举值
10. flag:是自己定义的,类似于 android:gravity="top",就是里面对应了自己的属性值。
12.reference|boolean:布尔值的资源文件
注意://由于reference是从资源文件中获取:所以在XML文件中写这个属性的时候必须 personattr:name="@string/app_name"这种格式,否则会出错
2.设置好属性文件后,在使用的布局中写相关配置:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:personattr="http://schemas.android.com/apk/res/com.example.declare_styleable"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent" >
5
6 <com.example.declare_styleable.PersonView
7 android:layout_width="wrap_content"
8 android:layout_height="wrap_content"
9 personattr:name="@string/person_name"
10 personattr:weight ="fat"
11 personattr:adult ="false"
12 personattr:textSize="@dimen/text_size"/>
13
14 </RelativeLayout>
这里要先应用这个attr:
1 xmlns:personattr="http://schemas.android.com/apk/res/com.example.declare_styleable"
对应结构是:
xmlns:你自己定义的名称="http://schemas.android.com/apk/res/你自定义的这个控件类所在的包" (我这是com.example.declare_styleable)
之后在布局中自定义的类中设相关属性:
你自己定义的名称:你设的属性 ="属性值";
3.最后在自定义控件的构造方法中获取你配置的属性值:
1 public class PersonView extends TextView {
2 public PersonView(Context context) {
3 super(context);
4 // TODO Auto-generated constructor stub
5 }
6
7 public PersonView(Context context, AttributeSet attrs, int defStyle) {
8 super(context, attrs, defStyle);
9 // TODO Auto-generated constructor stub
10 }
11
12 public PersonView(Context context, AttributeSet attrs) {
13 super(context, attrs);
14 // TODO Auto-generated constructor stub
15 TypedArray tArray = context.obtainStyledAttributes(attrs,R.styleable.PersonAttr);//获取配置属性
16 String name = tArray.getString(R.styleable.PersonAttr_name);<span style="font-family: Arial, Helvetica, sans-serif;">//得到属性name</span>
17 int age = tArray.getInt(R.styleable.PersonAttr_age, 15);
18 Boolean adult = tArray.getBoolean(R.styleable.PersonAttr_adult, false);
19 String str_adult = getAdultStatus(adult);
20 int weight = tArray.getInt(R.styleable.PersonAttr_weight, 1);// 默认是中等身材,属性为:1
21 String str_weight = getWeightStatus(weight);//获得肥胖属性
22 float textSize = tArray.getDimension(R.styleable.PersonAttr_textSize,R.dimen.default_text_size);// 如果你设置为DP等单位,会做像素转换
23 tArray.recycle();//回收资源
24 // setTextSize(textSize);//设置字体大小
25 setText("姓名:" + name + "\n" + "年龄:" + age + "\n" + "是否成年:" + str_adult
26 + "\n" + "体形:" + str_weight);//给自定义的控件赋值
27 }
28
29 /** 根据传入的值判断是否成年 */
30 public String getAdultStatus(Boolean adult ){
31 String str_adult = "未成年";
32 if (adult) {
33 str_adult = "成年";
34 }
35 return str_adult;
36 }
37
38 /** 根据传入的值判断肥胖状态 */
39 public String getWeightStatus(int weight){
40 String str_weight = "中等";
41 switch (weight) {
42 case 0:
43 str_weight = "瘦";
44 break;
45 case 1:
46 str_weight = "中等";
47 break;
48 case 2:
49 str_weight = "肥胖";
50 break;
51 default:
52 break;
53 }
54 return str_weight;
55 }
56 }
运行后就是:

这样,以后我们就可以根据这个方法,去自定义控件并自定义配置属性了,大大提高了自定义布局的使用效率。
对应的源码下载地址:下载地址
转载地址:http://blog.csdn.net/vipzjyno1/article/details/23696537
[学习总结]8、android 自定义控件 使用declare-styleable进行配置属性(源码角度)的更多相关文章
- android 自定义控件 使用declare-styleable进行配置属性(源码角度)
android自定义styleableattrs源码 最近在模仿今日头条,发现它的很多属性都是通过自定义控件并设定相关的配置属性进行配置,于是便查询了解了下declare-styleabl ...
- 【转】android 自定义控件 使用declare-styleable进行配置属性(源码角度)
原文网址:http://blog.csdn.net/vipzjyno1/article/details/23696537 最近在模仿今日头条,发现它的很多属性都是通过自定义控件并设定相关的配置属性进行 ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃(二)
1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...
- Android事件传递机制详解及最新源码分析——View篇
摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 对于安卓事件传递机制相信绝大部分开发者都听说过或者了解过,也是面试中最常问的问题之一.但是真正能从源码角度理解具体事件传递流程的相信并不多, ...
- Android网络框架OkHttp之get请求(源码初识)
概括 OkHttp现在很火呀.于是上个星期就一直在学习OkHttp框架,虽然说起来已经有点晚上手了,貌似是2013年就推出了.但是现在它版本更加稳定了呀.这不,说着说着,OkHttp3.3版本在这几天 ...
- Android多线程之(一)View.post()源码分析——在子线程中更新UI
提起View.post(),相信不少童鞋一点都不陌生,它用得最多的有两个功能,使用简便而且实用: 1)在子线程中更新UI.从子线程中切换到主线程更新UI,不需要额外new一个Handler实例来实现. ...
- MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)
前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...
- 《Android NFC 开发实战详解 》简介+源码+样章+勘误ING
<Android NFC 开发实战详解>简介+源码+样章+勘误ING SkySeraph Mar. 14th 2014 Email:skyseraph00@163.com 更多精彩请直接 ...
- Android反编译(一)之反编译JAVA源码
Android反编译(一) 之反编译JAVA源码 [目录] 1.工具 2.反编译步骤 3.实例 4.装X技巧 1.工具 1).dex反编译JAR工具 dex2jar http://code.go ...
- android Service Activity三种交互方式(付源码)(转)
android Service Activity三种交互方式(付源码) Android应用服务器OSBeanthread android Service Binder交互通信实例 最下边有源代码: ...
随机推荐
- CTF-Tools 一款CTF古典密码加解密工具
CTF-Tools 一款CTF古典密码加解密工具 工具截图 工具简介 一款CTF编码.解码.加密.解密工具. 支持的编码解码: URL-UTF-8 URL-GB2312 Unicode Escape( ...
- 3D 穿梭效果?使用 CSS 轻松搞定
背景 周末在家习惯性登陆 Apex,准备玩几盘.在登陆加速器的过程中,发现加速器到期了. 我一直用的腾讯网游加速器,然而点击充值按钮,提示最近客户端升级改造,暂不支持充值(这个操作把我震惊了~).只能 ...
- Netty数据如何在 pipeline 中流动
前言 在之前文章中,我们已经了解了pipeline在netty中所处的角色,像是一条流水线,控制着字节流的读写,本文,我们在这个基础上继续深挖pipeline在事件传播 Unsafe对象 顾名思义,u ...
- GO语言数据结构之链表
链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分: ...
- Android LayoutInflater(布局填充器)
先来看一下LayoutInflater的基本用法吧,它的用法非常简单,首先需要获取到LayoutInflater的实例,有两种方法可以获取到,第一种写法如下: LayoutInflater layou ...
- [loj6278]数列分块入门2
做法1 以$K$为块大小分块,并对每一个块再维护一个排序后的结果,预处理复杂度为$o(n\log K )$ 区间修改时将整块打上标记,散块暴力修改并归并排序,单次复杂度为$o(\frac{n}{K}+ ...
- [cf1479E]School Clubs
对于当前班级状态$S$,定义一个函数$\varphi(S)$,要求其满足: 令结束状态为$S_{end}$,对于任意$S\ne S_{end}$,若其下一个状态为$S'$,则$E(\varphi(S) ...
- [cf1479D]Odd Mineral Resource
先考虑判定是否有解,注意到无解即每一个数都出现偶数次,根据异或的性质,只需要随机$V_{i}$,假设$u$到$v$路径上所有节点构成集合$S$,若$\bigoplus_{x\in S,l\le a_{ ...
- [luogu7116]微信步数
先判定无解,当且仅当存在一个位置使得移动$n$步后没有结束且仍在原地 暴力枚举移动的步数,记$S_{i}$为移动$i$步(后)未离开范围的点个数,则恰好移动$i$步的人数为$S_{i-1}-S_{i} ...
- [bzoj5295]染色
将这张图化简,不断删掉度为1的点(类似于拓扑排序),构成了一张由环组成的图考虑一个连通块中,设点数为n,边数为m(已经删掉了度为1的点),那么一共只有三种情况:1.一个环($n=m$),一定为YES2 ...