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 + " " + "年龄:" + age + " " + "是否成年:" + str_adult 26 + " " + "体形:" + 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