android AttributeSet API 之开发案例

android AttributeSet API 之开发案例

在通过xml文件构造view组件的时候,往往都要使用到AttributeSet和defStyle这个两个参数。
 public class myButton extends Button{
public myButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar, defStyle, 0);
}
}

此时,
context会调用obtainStyledAttributes( AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)方法获得一个TypedArray,然后根据这个TypeArray来设置组件的属性。obtainStyledAttributes这类方法有好几个,真正的实现是Resources.Theme类,分别是:
   obtainStyledAttributes( AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) : TypedArray
   obtainStyledAttributes( int resid, int[] attrs)  : TypeArray
   obtainStyledAttributes(int[] attrs) : TypeArray
在第一种方法里根据attrs确定要获取哪些属性,然后依次通过其余3个参数来取得相应的属性值,属性值获取的优先级从高到低依次是set, defStyleAttr, defStyleRes. defStyleAttr是一个reference, 它指向当前Theme中的一个style, style其实就是各种属性的集合,如果defStyleAttr为0或者在Theme中没有找到相应的style, 则 才会尝试从defStyleRes获取属性值,defStyleRes表示的是一个style的id, 当它为0时也无效。方法(2)和(3)分别表示从style或Theme里获取属性值。
例如:
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar, defStyle, 0);


 attr是在/res/values/attrs.xml文件下定义的,除了系统组件本身的属性,我们也可以自定义属性,然后在layout布局中使用。attrs.xml里通常包括若干个attr集合,例如
<declare-styleable name="LabelView">
        <attr name="text" format="string" />
        <attr name="textColor" format="color" />
        <attr name="textSize" format="dimension" />
    </declare-styleable>
 就表示一个attr集合,declare-styleable标签里的name值表示的就是上面方法里的attrs参数,android会自动在R文件中生成一个数组, 它可以使任意的不一定要是view组件名称。在集合里定义每个属性的名称和它的类型,据偶所见总共有reference, string, color, dimension, boolean等,如果允许多个类型可以用"|"来隔开,比如reference | color, attr还可以这样定义
 <attr name="layout_height" format="dimension">
       <enum name="fill_parent" value="-1" />
       <enum name="match_parent" value="-1" />
       <enum name="wrap_content" value="-2" />
    </attr>
当attr的定义没有指明format时,表示它已经在其他地方定义过了,所以你可以定义一个attr集合,里面的都是已经定义好的属性(例如系统组件的属性), 然后通过obtainStyledAttributes方法来获取这些属性值,例如
<declare-styleable name="Gallery1">
        <attr name="android:galleryItemBackground" />
    </declare-styleable>
当然,我们也需要声明自己的命名空间
xmlns:app="http://schemas.android.com/apk/res/your_package_name"

 R文件中会有styleable和attr这两个类,当我们要使用哪个属性集合或哪个属性的时候用的是styleable, 而attr类定义的仅仅是attr这个属性在layout中的id. AttributeSet有两个方法分别是
    int getAttributeNameResource(int index);
    int getAttributeResourceValue(int index, int defaultValue);
前一个方法获取的就是attr属性名称的id,也也就是attr类定义的数值,后一个方法获取的才是attr属性值。

例如,如果我们希望自定义ActionBar以适应不同的场景需要
<com.jeason.jeasonactionbar.MyActionBar
xmlns:bar="http://schemas.android.com/apk/res/com.jeason.jeasonmapraiders"
android:layout_height="@dimen/gd_action_bar_height"
android:layout_width="fill_parent"
android:layout_alignParentTop="true"
bar:type="normal"
bar:title="Campus Map"/>

public class MyActionBar extends LinearLayout {
private CharSequence mTitle;
private MyActionBar.Type mType;
    public enum Type {
Normal,
Dashboard,
Dashboard
}
ublic MyActionBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar, defStyle, 0);
mTitle = a.getString(R.styleable.ActionBar_title);
int layoutID;
int type = a.getInteger(R.styleable.ActionBar_type, -1);
switch (type) {
case 2:
mType = Type.Empty;
layoutID = R.layout.gd_action_bar_empty;
break;
case 1:
mType = Type.Dashboard;
layoutID = R.layout.gd_action_bar_dashboard;
break;
case 0:
default:
mType = Type.Normal;
layoutID = R.layout.gd_action_bar_normal;
break;
}
LayoutInflater.from(context).inflate(layoutID, this);
a.recycle();
}


相应的在values/attrs.xml文件中
<declare-styleable name="ActionBar">
<attr name="title" format="string" />
<attr name="type">
<enum name="normal" value="0" />
<enum name="dashboard" value="1" />
<enum name="empty" value="2" />
</attr>
</declare-styleable>





郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。