在android開發過程中,用到系統的View時候可以通過XML來定義一些View的屬性。比如ImageView:


android:src 和android:scaleType為ImageView指定了圖片源和圖片縮放類型。
其實我們也可以自定義圖片的這種屬性。
下面以自定義標題欄為例,簡單說明下自定義View屬性。
比如在項目中,經常會用到標題欄,左邊是返回,中間是標題,右邊是下一步。如下圖:


如果,每一次用到標題都在XML里面進行布局,那就太麻煩了。我們可以自定義一個標題欄。
自定義View的方式基本有三種:
1,繼承View類,比如 View ImageView。
2,組合的方式,就是把已知的多個View組合在一起。也是通過繼承其中一個View,用動態加載的方式,把其他View組合到一起。
3,繼承ViewGroup類,比如我們熟悉的五大布局,ViewPager等。
我們使用第二種,組合的方式。


在構造函數中,動態的把標題欄的xml文件加載進去。


common_title.xml:
xml version="1.0" encoding ="utf-8" ?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width= "fill_parent" android:layout_height= "match_parent" android:layout_gravity= "center" android:background= "#123456" > <LinearLayout android:id="@+id/left_ll" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:gravity="center_vertical|left" android:orientation="horizontal" > <ImageView android:id="@+id/left_iv" android:layout_width="25dip" android:layout_height="match_parent" android:src="@drawable/back" android:layout_marginLeft="10dip" /> < TextView android:id="@+id/left_tv" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dip" android:gravity="center_vertical" android:textColor="#ffffff" android:text="返回" android:textSize="16sp" /> </LinearLayout> <LinearLayout android:id="@+id/right_ll" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentRight="true" android:orientation="horizontal" > <ImageView android:id="@+id/right_iv" android:layout_width="25dip" android:layout_height="match_parent" android:src="@drawable/next" android:layout_marginLeft="10dip" /> < TextView android:id="@+id/right_tv" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dip" android:gravity="center_vertical" android:textColor="#ffffff" android:text="下一步" android:textSize="16sp" /> </LinearLayout> <LinearLayout android:id="@+id/middle_ll" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_toLeftOf="@id/right_ll" android:layout_toRightOf="@id/left_ll" android:gravity="center_horizontal" android:orientation="horizontal" > < TextView android:id="@+id/middle_tv" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="我是標題" android:gravity="center_vertical" android:textColor="#ffffff" android:textSize="16sp" /> <ImageView android:id="@+id/middle_iv" android:layout_width="25dip" android:layout_height="match_parent" android:src="@drawable/click_down" /> </LinearLayout> </RelativeLayout>
<?
OK,現在CommmTitleView已經是有界面的View了,我們在XML中直接使用可以使用了。


圖中,my: 開頭的就是自定義屬性,我定義了CommonTitleView的左邊圖片,左邊文字,右邊圖片等。接下來就接着講如何實現。
首先要在value文件夾下建立attr.xml:
<?xml version="1.0" encoding ="utf-8" ?> <resources> <declare-styleable name= "CommonTitleView"> < attr name= "leftTv" format ="integer" /> < attr name= "leftIv" format ="integer" /> < attr name= "rightTv" format ="integer" /> < attr name= "rightIv" format ="integer" /> < attr name= "middleTv" format ="integer" /> < attr name= "middleIv" format ="integer" /> </declare-styleable> </resources>
這個文件聲明了有哪些自定義屬性。其中 attr:name 是自定義屬性的名稱,format后面是該屬性的類型。
format屬性有:
reference 表示引用,參考某一資源ID
string 表示字符串
color 表示顏色值
dimension 表示尺寸值
boolean 表示布爾值
integer 表示整型值
float 表示浮點值
fraction 表示百分數
enum 表示枚舉值
flag 表示位運算
attr.xml就是聲明了這個View有哪些屬性,屬性名稱是什么,屬性類型是什么。
然后,在聲明下命名空間,就可以使用自己定義的這些屬性了。


第一行,是系統的命名空間。
第二行,xmlns:my就是我們APP自身的命名空間。聲明后,就可以使用我們在attr.xml中聲明的屬性了。
那么,在XML中聲明這些屬性后,如何讓CommonTitleView知道我們聲明了哪些屬性呢?
這就需要在CommontitleView,構造函數中,獲取這些屬性,然后根據獲取的屬性值,做出處理。如下圖:


在構造函數中,我們使用TypedArray把在xml文件中聲明的屬性裝起來。關於TypedArray的介紹,源碼里面很簡單:就是裝屬性的容器。
然后依次,通過我們在attr.xml中設置的屬性名稱,獲取對應的值。
比如,xml中寫的是my:leftIv="@drawble/back"
在構造函數中通過
int resouce_left_iv = typedArray.getResourceId ( R.styleable.CommonTitleView_leftIv, 0);
得到資源文件back圖片的資源ID。
R. styleable .CommonTitleView_leftIv的意思就是名稱為CommonTitleView的leftIv屬性。
那么,resouce_left_iv 就是圖片back對應的資源ID.
其他的屬性都是通過上述方法添加進去的,比如文字等。
拿到資源ID后,就可以把資源設置到定義的View中。

這樣,我們自定義的標題欄就OK了。
除此之外,還可以為標題欄中的返回,下一步等設置監聽。

還可以定義接口,在外部使用的時候動態的來設定標題欄中的內容:

下面是在Activity中使用的例子:
現在main.xml中定義

在Activity中自由的設置監聽:

最后附上源碼:http://pan.baidu.com/s/1ntxiPTn