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集合,例如


就表示一個attr集合,declare-styleable標簽裡的name值表示的就是上面方法裡的attrs參數,android會自動在R文件中生成一個數組, 它可以使任意的不一定要是view組件名稱。在集合裡定義每個屬性的名稱和它的類型,據偶所見總共有reference, string, color, dimension, boolean等,如果允許多個類型可以用"|"來隔開,比如reference | color, attr還可以這樣定義


當attr的定義沒有指明format時,表示它已經在其他地方定義過瞭,所以你可以定義一個attr集合,裡面的都是已經定義好的屬性(例如系統組件的屬性), 然後通過obtainStyledAttributes方法來獲取這些屬性值,例如


當然,我們也需要聲明自己的命名空間

xmlns:app="https://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以適應不同的場景需要


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文件中


發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *