接觸Android UI開發的這段時間以來,對自定義組合控件有了必定的瞭解,爲此小結一下,本文小結內容主要討論的是如何使用Android SDK提供的佈局和控件組成一個功能完整組合控件並將其封裝爲面向對象的類,而並不是討論如何繼承自SDK提供的控件類(好比TextView),對其進行自定義擴展的問題。android
進入正題前,咱們先來看一組功能需求框架
假設在手機需求上,那麼如上三個界面咱們能夠使用三個Activity,每一個Activity一個佈局文件,實現起來比較獨立,可是假設在Android pad上要求如上三個界面在一個對話框上實現,並且切換過程當中要有漸變更畫,那麼該如何實現呢?個人方案是經過使用一個浮動的Activity外加ViewFlipper來實現。雖然咱們能夠在這個浮動的Activity類內可以獲取到每一個界面的控件並添加相應的操做,可是若是所有放在一個Activity類內,會使這個類內代碼量很大,代碼走讀起來也不容易,並且也少了些OO的概念,爲此能夠考慮將每個界面用一個自定義的組合控件類來實現。同理,假設上面的第一個界面裏面關於微博綁定的列表界面,咱們能夠考慮使用ListView控件外加一個自定義擴展的Adapter,其中的每一項,其實也是一個組合控件,須要咱們在自定義的Adapter中建立出來。爲了嘗試自定義組合控件的使用,對於微博列表我也沒有使用ListView來實現,而是採用了基礎的addView方式。eclipse
下面具體分步驟來講明自定義組合控件的實現和封裝:ide
這一步和其它新建和編寫佈局資源的方法同樣,能夠使用拖動控件,也能夠使用代碼輸入,亦能夠經過其它第三方開發工具編寫,總之,結果是要獲得一個知足需求的佈局,爲了後面行文的方便,我就取上面第二個界面佈局account_info_preview.xml中的部分代碼來講明下函數
<?xml version="1.0" encoding="utf-8"?>工具
<LinearLayout佈局
xmlns:android="http://schemas.android.com/apk/res/android"開發工具
android:orientation="vertical"動畫
android:layout_width="fill_parent"spa
android:layout_height="fill_parent"
android:background="@drawable/login_view_back">
<RelativeLayout
android:layout_height="@dimen/content_top_land_height"
android:layout_width="fill_parent"
android:padding="@dimen/login_title_padding"
android:background="@drawable/login_title_back">
……
</RelativeLayout>
</LinearLayout>
這一步的實現要求就是經過所見即所得的原理,使得編輯完後佈局在Graphical Layout界面看到的效果就是你想要實現的界面的靜態效果就能夠了。
上面的account_info_preview.xml佈局文件建立好以後,就能夠爲這個組合控件的佈局建立一個你須要的自定義類了,假設這個類被命名爲AccountInfoPreView類,那麼經過eclipse先建立該類,該類的父類就是組合控件根元素對應的類,這裏是LinearLayout,因此這個AccountInfoPreView就應該派生自LinearLayout。
LinearLayout有兩個構造函數,在AccountInfoPreView類中咱們必須重寫父類的構造函數,因爲在使用中,咱們不採用直接new AccountInfoPreView(Context context)方式建立該組合控件,因此咱們只須要重載一個public AccountInfoPreView(Context context, AttributeSet attrs)構造函數就能夠了,這個就看你自定義的組合控件的需求了。
另外爲了在自定義類中進行對控件對象的實例化,咱們須要重寫protected void onFinishInflate()函數,以實現資源id和控件對象的一一對應。下面以貼出代碼爲例
package com.netease.pris.hd.view;
……
public class AccountInfoPreView extends LinearLayout
{
TextView mViewTitle;
ImageView mHeader;
public AccountInfoPreView(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
protected void onFinishInflate()
{
mViewTitle =(TextView)findViewById(R.id.aip_title_text);
mHeader = (ImageView)findViewById(R.id.aip_header_imgae);
}
……
}
如上就爲自定義控件類搭好了框架,具體須要進行何種操做,就往裏面寫操做就能夠了,好比添加控件點擊事件等等。
自定義組合控件的類有了,自定義組合控件的佈局也有了,雖然類內也用findViewById對組合控件內部的控件進行了一一實例化,可是整個組合控件類和佈局尚未創建起關聯關係,這一步就經過用自定義類的包名+類名來修改自定義組合控件佈局的根元素完成。咱們看到咱們上面的自定義類的包名爲com.netease.pris.hd.view,類名爲AccountInfoPreView,因此咱們從新將上面的account_info_preview.xml內的LinearLayout根元素替換爲AccountInfoPreView就能夠了。具體以下示例
<?xml version="1.0" encoding="utf-8"?>
<com.netease.pris.hd.view.AccountInfoPreView
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/login_view_back">
<RelativeLayout
android:layout_height="@dimen/content_top_land_height"
android:layout_width="fill_parent"
android:padding="@dimen/login_title_padding"
android:background="@drawable/login_title_back">
……
</RelativeLayout>
</com.netease.pris.hd.view.AccountInfoPreView>
好了,上面已經將建立自定義組合控件的步驟介紹完了,也建立了一個AccountInfoPreView的自定義組合控件,接下來咱們就要講解使用這個自定義組合控件了。
根據資源加載的靜態和動態兩種方式,使用自定義組合控件,也一樣有靜態和動態兩種方式,其實也很簡單的兩種方式,跟Android的Inflate有關係。
這裏所說的靜態加載,就是自定義組合控件被使用它的佈局在XML資源中包含了,而這個佈局又經過Activity的setConentView()函數設置進去了,那麼咱們就能夠經過findViewById的方式來實例化自定義組合控件的對象。
好比上面建立的AccountInfoPreView自定義組合控件被Activity的setConentView函數設置的佈局account_view_flipper.xml所包含,其內容以下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="@dimen/login_dialog_width"
android:layout_height="@dimen/login_dialog_height">
<ViewFlipper
android:id="@+id/account_view_flippe"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include
android:id="@+id/account_info_preview"
layout="@layout/account_info_preview" />
</ViewFlipper>
</LinearLayout>
咱們就能夠經過findViewById的方法來實例化自定義組合控件的對象,代碼以下
AccountInfoPreView mAIPView = (AccountInfoPreView)findViewById(R.id.account_info_preview);
成功實例化了對象,至於後面對該對象的具體使用就不羅列了。
動態加載,就是自定義組合控件在資源佈局中沒有包含,咱們經過代碼動態建立到所須要的ViewGroup中去。因爲自定義組合控件,不像TextView等基礎控件或自定義的不關聯資源的View,因此不能經過new方式直接進行建立,須要經過Inflate方法實例化自定義組合控件對象,並將其添加到ViewGroup中去,咱們能夠改寫下上面的佈局account_view_flipper.xml文件爲
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="@dimen/login_dialog_width"
android:layout_height="@dimen/login_dialog_height">
<ViewFlipper
android:id="@+id/account_view_flippe"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</ViewFlipper>
</LinearLayout>
則在Activity的onCreate函數中咱們能夠以下編寫代碼
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.account_view_flipper);
ViewFlipper mViewFlipper =(ViewFlipper)findViewById(R.id.account_view_flippe);
AccountInfoPreView mAIPView = (AccountInfoPreView)getLayoutInflater().inflate(R.id.account_info_preview, null);
mViewFlipper.addView(mAIPView);
}
經過上面的代碼,咱們一樣實例化了一個AccountInfoPreView控件對象,並將其動態加載到了界面上進行顯示。具體操做一樣根據具體需求來實現,這裏就不作展開了。
關於Android自定義組合控件就小結到這裏,假如文中有不正確的地方還望幫忙斧正,謝謝。