標籤:android attribute
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 stubTypedArray 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.MyActionBarxmlns: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>
android AttributeSet API 之開發案例