android:建立自定義控件

在前面兩節咱們已經學習了 Android 中的一些常見控件以及基本佈局的用法,不過當時 咱們並無關注這些控件和佈局的繼承結構,如今是時候應該看一下了,如圖 3.26 所示。android

 

 

 

 

 

圖   3.26ide

 

能夠看到,咱們所用的全部控件都是直接或間接繼承自 View 的,所用的全部佈局都是 直接或間接繼承自 ViewGroup 的。View 是 Android 中一種最基本的 UI 組件,它能夠在屏幕 上繪製一塊矩形區域,並能響應這塊區域的各類事件,所以,咱們使用的各類控件其實就是 在 View 的基礎之上又添加了各自特有的功能。而 ViewGroup 則是一種特殊的 View,它能夠 包含不少的子 View 和子 ViewGroup,是一個用於放置控件和佈局的容器。函數

這個時候咱們就能夠思考一下,若是系統自帶的控件並不能知足咱們的需求時,可不可 以利用上面的繼承結構來建立自定義控件呢?答案是確定的,下面咱們就來學習一下建立自 定義控件的兩種簡單方法。先將準備工做作好,建立一個 UICustomViews 項目。佈局

 

3.4.1    引入佈局學習

 

若是你用過 iPhone 應該會知道,幾乎每個 iPhone 應用的界面頂部都會有一個標題欄, 標題欄上會有一到兩個按鈕可用於返回或其餘操做(iPhone 沒有實體返回鍵)。如今不少的 Android 程序也都喜歡模仿 iPhone 的風格,在界面的頂部放置一個標題欄。雖然 Android 系 統已經給每一個活動提供了標題欄功能,但這裏咱們仍然決定不使用它,而是建立一個自定義 的標題欄。ui

通過前面兩節的學習,我想建立一個標題欄佈局對你來講已經不是什麼困難的事情了, 只須要加入兩個 Button 和一個 TextView,而後在佈局中擺放好就能夠了。但是這樣作卻存 在着一個問題,通常咱們的程序中可能有不少個活動都須要這樣的標題欄,若是在每一個活的佈局中都編寫一遍一樣的標題欄代碼,明顯就會致使代碼的大量重複。這個時候咱們就可this

以使用引入佈局的方式來解決這個問題,新建一個佈局 title.xml,代碼以下所示:xml

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/title_bg" >對象

 

<Button android:id="@+id/title_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="5dip" android:background="@drawable/back_bg" android:text="Back" android:textColor="#fff" />blog

 

<TextView android:id="@+id/title_text" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_weight="1" android:gravity="center" android:text="Title Text" android:textColor="#fff" android:textSize="24sp" />

 

<Button android:id="@+id/title_edit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="5dip" android:background="@drawable/edit_bg" android:text="Edit" android:textColor="#fff" />

 

</LinearLayout>

 

 

 

能夠看到,咱們在 LinearLayout 中分別加入了兩個 Button 和一個 TextView,左邊的 Button

可用於返回,右邊的 Button 可用於編輯,中間的 TextView 則能夠顯示一段標題文本。上面 的代碼中大多數的屬性你都已是見過的,下面我來講明一下幾個以前沒有講過的屬性。 android:background 用於爲佈局或控件指定一個背景,可使用顏色或圖片來進行填充,這 裏我提早準備好了三張圖片,title_bg.png、back_bg.png 和 edit_bg.png,分別用於做爲標題欄、 返回按鈕和編輯按鈕的背景。另外在兩個 Button 中咱們都使用了 android:layout_margin 這個屬 性,它能夠指定控件在上下左右方向上偏移的距離,固然也可使用 android:layout_marginLeft 或 android:layout_marginTop 等屬性來單獨指定控件在某個方向上偏移的距離。

如今標題欄佈局已經編寫完成了,剩下的就是如何在程序中使用這個標題欄了,修改

activity_main.xml 中的代碼,以下所示:

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" >

 

<include layout="@layout/title" />

 

 

</LinearLayout>

沒錯!咱們只須要經過一行 include 語句將標題欄佈局引入進來就能夠了。 最後別忘了在 MainActivity 中將系統自帶的標題欄隱藏掉,代碼以下所示:

 

public class MainActivity extends Activity {

 

 

@Override

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_main);

}

 

 

}

如今運行一下程序,效果如圖 3.27 所示。

 

 

圖   3.27

 使用這種方式,無論有多少佈局須要添加標題欄,只需一行 include 語句就能夠了。

 

3.4.2    建立自定義控件

 

引入佈局的技巧確實解決了重複編寫佈局代碼的問題,可是若是佈局中有一些控件要求 可以響應事件,咱們仍是須要在每一個活動中爲這些控件單獨編寫一次事件註冊的代碼。好比 說標題欄中的返回按鈕,其實不論是在哪個活動中,這個按鈕的功能都是相同的,即銷燬 掉當前活動。而若是在每個活動中都須要從新註冊一遍返回按鈕的點擊事件,無疑又是增 加了不少重複代碼,這種狀況最好是使用自定義控件的方式來解決。

新建 TitleLayout 繼承自 LinearLayout,讓它成爲咱們自定義的標題欄控件,代碼以下 所示:

 

public class TitleLayout extends LinearLayout {

 

 

public TitleLayout(Context context, AttributeSet attrs) {

super(context, attrs);

LayoutInflater.from(context).inflate(R.layout.title, this);

}

 

}

 

 

 

首先咱們重寫了 LinearLayout 中的帶有兩個參數的構造函數,在佈局中引入 TitleLayout

控件就會調用這個構造函數。而後在構造函數中須要對標題欄佈局進行動態加載,這就要借 助 LayoutInflater 來實現了。經過 LayoutInflater 的 from()方法能夠構建出一個 LayoutInflater 對象,而後調用 inflate()方法就能夠動態加載一個佈局文件,inflate()方法接收兩個參數,第 一個參數是要加載的佈局文件的 id,這裏咱們傳入 R.layout.title,第二個參數是給加載好的 佈局再添加一個父佈局,這裏咱們想要指定爲 TitleLayout,因而直接傳入 this。

如今自定義控件已經建立好了,而後咱們須要在佈局文件中添加這個自定義控件,修改

activity_main.xml 中的代碼,以下所示:

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" >

 

<com.example.uicustomviews.TitleLayout android:layout_width="match_parent" android:layout_height="wrap_content"

></com.example.uicustomviews.TitleLayout>

 

 

</LinearLayout>

添加自定義控件和添加普通控件的方式基本是同樣的,只不過在添加自定義控件的時候 咱們須要指明控件的完整類名,包名在這裏是不能夠省略的。

從新運行程序,你會發現此時效果和使用引入佈局方式的效果是同樣的。 而後咱們來嘗試爲標題欄中的按鈕註冊點擊事件,修改 TitleLayout 中的代碼,以下所示:

 

public class TitleLayout extends LinearLayout {

 

 

public TitleLayout(Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater.from(context).inflate(R.layout.title, this); Button titleBack = (Button) findViewById(R.id.title_back); Button titleEdit = (Button) findViewById(R.id.title_edit); titleBack.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) { ((Activity) getContext()).finish();

}

});

titleEdit.setOnClickListener(new OnClickListener() {

@Override

 

 

 

public void onClick(View v) {

Toast.makeText(getContext(), "You clicked Edit button",

Toast.LENGTH_SHORT).show();

}

});

}

 

}

首先仍是經過 findViewById()方法獲得按鈕的實例,而後分別調用 setOnClickListener() 方法給兩個按鈕註冊了點擊事件,當點擊返回按鈕時銷燬掉當前的活動,當點擊編輯按鈕時 彈出一段文本。從新運行程序,點擊一下編輯按鈕,效果如圖 3.28 所示。

 

 

 

圖   3.28

 

這樣的話,每當咱們在一個佈局中引入 TitleLayout,返回按鈕和編輯按鈕的點擊事件就 已經自動實現好了,也是省去了不少編寫重複代碼的工做。

相關文章
相關標籤/搜索