对于自定义控件来说,怎样定义它的属性,如何使用,到运用这三个过程。举一个例子表达这些过程,将标题栏的布局封装到自定义view中,方便调用。
1 在attr.xml 文件中声明属性格式,以及 定义属性集合
<attr name="text" format="string"/>
<attr name= "left_enable" format = "boolean"/>
<attr name="right_enable format="boolean"/>
<declare-styleable name="TitleView">
<attr name="text"></attr>
<attr name="left_enable"></attr>
<attr name="right_enable"></attr>
<attr name="left_icon"></attr>
<attr name="right_icon"></attr>
</declare-styleable>
2. 布局文件 xml 中使用:
先在根结点声明空间,然后通过空间引用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:li="http://schemas.android.com/apk/res/com.wxtcapp.ui"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f2f0eb"
android:orientation="vertical" >
<com.wxtcapp.view.TitleView
android:layout_width="match_parent"
android:layout_height="wrap_content"
li:text="登录"
/>
3 在自定义控件类 的构造方法,获取xml写入属性所对应的值,放在自己属性内。
</pre><pre name="code" class="java">
public TitleView(Context context,AttributeSet attrs){
super(context,attrs);
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.TitleView);
int n = a.getIndexCount();
for( int i= 0;i<n;i++){
int attr = a.getIndex(i);
switch(attr){
case R.styleable.TitleView_text:
mTitle = a.getString(attr);
break;
case R.styleable.TitleView_left_enable:
leftEnable = a.getBoolean(attr,false);
break;
case R.styleable.TitleView_right_enable:
rightEnable = a.getBoolean(attr,false);
break;
}
}
}
我们知道如何去使用自定义属性去管理我们的控件,知其然的同时还要知其所以然,为什么整个流程是这样子?
从几个过程中看到从属性值 xml -》 AttributeSet --> TypeArray -- > 具体值 在这些类流转。
首先 AttributeSet 是什么?
它位于 android.util.AttributeSet ,这个类是为了解析xml文件的辅助类。它提供了一系列api获得xml文件中的属性或者值。
其中有
public String getIdAttribute(): 获得的id属性对应的字符串
public String getClassAttribute() 获得该控件所对应的类
public String getAttributeName(int index) 根据位置获得属性名
public String getAttributeValue(int index) 根据位置获得属性值
等一系列操作xml的api
测试遍历该控件下的所有属性的所有值,可以这样写:
public TextView(Context context,Attribute attrs,int defStyle){
int attributeCount = attrs.getAttribute();// 获取属性的数目
for(int i=0;i<attributeCount;i++){
String aAttributeName = attrs.getAttributeName(i); // 根据属性位置获得相应属性名称
String aAttributeValue = attrs.getAttributeValue(i); //根据位置获得属性值
log.i(TAG,"attributeName:"+aAttributeName+" attributeValue:"+aAttributeValue);
}
}
然后是 TypeArray,对Attribute的进一步抽象,使得获取属性值更加方便。
TypeArray a = context.obtainStyledAttributes(attrs,com.android.internal.R.styleable.XXX,defStyle,0);
将所有attrs里面属性遍历找出 styleable中的属性(即自己想要获取的属性)进行封装,使得可以直接通过R.syleabled.ViewName_attributeName这样形式获取属性值。
(观察 R.styleable.TitleView_text 之类的发现 它的值并不像一般android R文件很长的id,而只是1,2之类的短int,其实这代表 该attr 在Styleabled的位置,通过规定好的特定的位置存储进去,然后以同样的位置获取出来。)
通过TypeArray可以直接获取属性值,上面的写法也可以是这样的:
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.TitleView);
mTitle = a.getString(R.styleable.TitleView_text);
leftEnable = a.getBoolean(R.styleable.TitleView_left_enable);
rightEnable = a.getBoolean(R.styleable.TitleView_right_enable);
其中俩个成员变量:
int[] mData; 包含了指定styleable中所有指定属性的值。