declare-styleable:declare-styleable是給自定義控件添加自定義屬性用的。
官方的相關(guān)內(nèi)部控件的配置屬性文檔:http://developer.android.com/reference/android/R.styleable.html
如果不知道如何查看源碼:點(diǎn)擊這里
起初,在自定義控件的時(shí)候,會(huì)要求構(gòu)造3個(gè)方法中的一個(gè)或多個(gè),好比我自定義的控件PersonView,
- public PersonView(Context context) {
- super(context);
- // TODO Auto-generated constructor stub
- }
- public PersonView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- // TODO Auto-generated constructor stub
- }
- public PersonView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
下面我們拿TextView的源碼看看AttributeSet是如何進(jìn)行操作的。
初始化時(shí)候,在布局文件中寫android:text="拉拉";
初始化TextView的時(shí)候,它的類中的屬性都會(huì)初始化;
接著往下看,你可以看到以下代碼:
- TypedArray a = theme.obtainStyledAttributes(
- attrs, com.android.internal.R.styleable.TextViewAppearance, defStyle, 0);
- TypedArray appearance = null;
- int ap = a.getResourceId(
- com.android.internal.R.styleable.TextViewAppearance_textAppearance, -1);
- a.recycle();
- if (ap != -1) {
- appearance = theme.obtainStyledAttributes(
- ap, com.android.internal.R.styleable.TextAppearance);
如果appearance不為空,它就會(huì)去尋找獲取相關(guān)屬性,接著往下看。
此時(shí)的text = ""; 就是準(zhǔn)備輸出的字符串初始化。
之后它便會(huì)查找你布局文件XML中是否設(shè)定給了它text屬性值
之前我們?cè)O(shè)定過(guò)android:text="拉拉"; 所以它便會(huì)得到相關(guān)的賦值,之后調(diào)用
- <span style="font-size:18px;"> setText(text, bufferType);
- if (hint != null) setHint(hint);
- </span>
同理也可以發(fā)現(xiàn),像hint,textcolor這類屬性都是這么初始化賦值的。
自定義控件并且自定義屬性的情況下,你可以通過(guò)這樣去獲取判斷是否配置了相關(guān)的屬性,并進(jìn)行賦值操作。
從源碼那邊我們大體知道了一個(gè)控件的屬性配置和初始化流程,下面就讓我們按照這個(gè)思路去自己學(xué)習(xí)下如何自定義配置。
下面我要寫一個(gè)繼承了TextView的PersonView類,給它設(shè)定屬性配置,之后實(shí)現(xiàn)屬性的顯示。
1.首先,先寫attrs.xml
在res-vlaues文件夾下創(chuàng)建資源文件attrs.xml或則自定義一個(gè)資源文件xx.xml,都可以。
之后在里面配置declare-styleable ,name為PersonAttr
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <declare-styleable name="PersonAttr">
- <attr name="name" format="reference" />
- <attr name="sex" format="reference" />
- <attr name="age" format="integer" />
- <attr name="weight">
- <flag name="fat" value="2" />
- <flag name="mid" value="1" />
- <flag name="thin" value="0" />
- </attr>
- <attr name="adult" format="boolean" />
- <attr name="textSize" format="dimension" />
- </declare-styleable>
- </resources>
我這里設(shè)置了姓名name,性別sex,年齡age,以及特征屬性weight(fat,mid,thin內(nèi)部的3個(gè)屬性及對(duì)應(yīng)的屬性值),還有是否成年adult,和TextView的字體大小textView。
可能這里有人會(huì)問(wèn),format是什么,里面的單詞代表的又是什么意思。
format就是格式,里面的就是這個(gè)屬性對(duì)應(yīng)的格式,下面列出來(lái)大致的格式有:
1. reference:參考某一資源ID,以此類推
(1)屬性定義:
<declare-styleable name = "名稱">
<attr name = "background" format = "reference" />
</declare-styleable>
(2)屬性使用:
<ImageView
android:layout_width = "42dip"
android:layout_height = "42dip"
android:background = "@drawable/圖片ID"
/>
2. color:顏色值
<declare-styleable name = "名稱">
<attr name = "textColor" format = "color" />
</declare-styleable>
3. boolean:布爾值
<declare-styleable name = "名稱">
<attr name = "focusable" format = "boolean" />
</declare-styleable>
4. dimension:尺寸值。注意,這里如果是dp那就會(huì)做像素轉(zhuǎn)換
<declare-styleable name = "名稱">
<attr name = "layout_width" format = "dimension" />
</declare-styleable>
5. float:浮點(diǎn)值。
6. integer:整型值。
7. string:字符串
8. fraction:百分?jǐn)?shù)。
9. enum:枚舉值
10. flag:是自己定義的,類似于 android:gravity="top",就是里面對(duì)應(yīng)了自己的屬性值。
注意://由于reference是從資源文件中獲取:所以在XML文件中寫這個(gè)屬性的時(shí)候必須 personattr:name="@string/app_name"這種格式,否則會(huì)出錯(cuò)
2.設(shè)置好屬性文件后,在使用的布局中寫相關(guān)配置:
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:personattr="http://schemas.android.com/apk/res/com.example.declare_styleable"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <com.example.declare_styleable.PersonView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- personattr:name="@string/person_name"
- personattr:weight ="fat"
- personattr:adult ="false"
- personattr:textSize="@dimen/text_size"/>
- </RelativeLayout>
這里要先應(yīng)用這個(gè)attr:
- xmlns:personattr="http://schemas.android.com/apk/res/com.example.declare_styleable"
對(duì)應(yīng)結(jié)構(gòu)是:
- xmlns:你自己定義的名稱="http://schemas.android.com/apk/res/你程序的package包名" (我這是com.example.declare_styleable)
包名是配置文件中 package="com.example.declare_styleable" 這樣格式的
之后在布局中自定義的類中設(shè)相關(guān)屬性:
你自己定義的名稱:你設(shè)的屬性 ="屬性值";
3.最后在自定義控件的構(gòu)造方法中獲取你配置的屬性值:
- public class PersonView extends TextView {
- public PersonView(Context context) {
- super(context);
- // TODO Auto-generated constructor stub
- }
- public PersonView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- // TODO Auto-generated constructor stub
- }
- public PersonView(Context context, AttributeSet attrs) {
- super(context, attrs);
- // TODO Auto-generated constructor stub
- TypedArray tArray = context.obtainStyledAttributes(attrs,R.styleable.PersonAttr);//獲取配置屬性
- String name = tArray.getString(R.styleable.PersonAttr_name);<span style="font-family: Arial, Helvetica, sans-serif;">//得到屬性name</span>
- int age = tArray.getInt(R.styleable.PersonAttr_age, 15);
- Boolean adult = tArray.getBoolean(R.styleable.PersonAttr_adult, false);
- String str_adult = getAdultStatus(adult);
- int weight = tArray.getInt(R.styleable.PersonAttr_weight, 1);// 默認(rèn)是中等身材,屬性為:1
- String str_weight = getWeightStatus(weight);//獲得肥胖屬性
- float textSize = tArray.getDimension(R.styleable.PersonAttr_textSize,R.dimen.default_text_size);// 如果你設(shè)置為DP等單位,會(huì)做像素轉(zhuǎn)換
- tArray.recycle();//回收資源
- // setTextSize(textSize);//設(shè)置字體大小
- setText("姓名:" + name + "\n" + "年齡:" + age + "\n" + "是否成年:" + str_adult
- + "\n" + "體形:" + str_weight);//給自定義的控件賦值
- }
- /** 根據(jù)傳入的值判斷是否成年 */
- public String getAdultStatus(Boolean adult ){
- String str_adult = "未成年";
- if (adult) {
- str_adult = "成年";
- }
- return str_adult;
- }
- /** 根據(jù)傳入的值判斷肥胖狀態(tài) */
- public String getWeightStatus(int weight){
- String str_weight = "中等";
- switch (weight) {
- case 0:
- str_weight = "瘦";
- break;
- case 1:
- str_weight = "中等";
- break;
- case 2:
- str_weight = "肥胖";
- break;
- default:
- break;
- }
- return str_weight;
- }
- }
這樣,以后我們就可以根據(jù)這個(gè)方法,去自定義控件并自定義配置屬性了,大大提高了自定義布局的使用效率。
對(duì)應(yīng)的源碼下載地址:下載地址