對AttributeSet和defStyle的理解
在通過xml文件構造view組件的時候,往往都要使用到AttributeSet和defStyle這個兩個參數,例如Button組件的構造方法Button(Context ctx, AttributeSet attrs, int defStyle)中,ctx會調用obtainStyledAttributes( AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)方法獲得一個TypedArray,然後根據這個TypeArray來設置組件的屬性。obtainStyledAttributes這類方法有好幾個,真正的實現是Resources.Theme類,分別是:
(1) obtainStyledAttributes( AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) : TypedArray
(2) obtainStyledAttributes( int resid, int[] attrs) : TypeArray
(3) obtainStyledAttributes(int[] attrs) : TypeArray
在方法(1)裏根據attrs確定要獲取哪些屬性,然後依次通過其餘3個參數來取得相應的屬性值,屬性值獲取的優先級從高到低依次是set, defStyleAttr, defStyleRes. defStyleAttr是一個reference, 它指向當前Theme中的一個style, style其實就是各種屬性的集合,如果defStyleAttr為0或者在Theme中沒有找到相應的style, 則 才會嚐試從defStyleRes獲取屬性值,defStyleRes表示的是一個style的id, 當它為0時也無效。方法(2)和(3)分別表示從style或Theme裏獲取屬性值。
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>
在layout布局中使用自定義的屬性,要指明包名稱,需要先定義,例如xmlns:app="https://schemas.android.com/apk/res/your_package_name", 然後就可以這樣app:text, app:textSize來設置屬性了。
R文件中會有styleable和attr這兩個類,當我們要使用哪個屬性集合或哪個屬性的時候用的是styleable, 而attr類定義的僅僅是attr這個屬性在layout中的id. AttributeSet有兩個方法分別是
int getAttributeNameResource(int index);
int getAttributeResourceValue(int index, int defaultValue);
前一個方法獲取的就是attr屬性名稱的id,也也就是attr類定義的數值,後一個方法獲取的才是attr屬性值。
最後更新:2017-04-02 06:51:56