Android 第八课 创建自定义控件
常用控件和布局的繼承結(jié)構(gòu),如下圖:
(待續(xù)。。。。)
所有的控件都是直接或間接繼承自View的,所用的所有布局都是直接或間接繼承自ViewGroup的,View是Android中最基本的一種UI組件,它可以在屏幕上繪制一塊矩形區(qū)域,并能響應(yīng)這塊區(qū)域的各種事件,ViewGroup是一中特殊的View,它可以包含很多的子View和子ViewGroup,是一個用于放置控件和布局的容器。
我們可以利用上面的繼承結(jié)構(gòu)來創(chuàng)建自定義控件,創(chuàng)建自定義控件的兩種簡單方法如下所示。
我們先創(chuàng)建一個UICustomViews項目。
1、引入布局
Android系統(tǒng)已經(jīng)給每個活動提供了標題欄功能,但我們決定先不使用它,而是創(chuàng)建一個自定義的標題欄。
只需要兩個Button和一個TextView,然后在布局中擺好就可以了,但是一般我們的程序中可能有很多個活動都需要這樣的標題欄,如果在每個活動的布局中都編寫一遍同樣的標題欄代碼,明顯的就會導(dǎo)致代碼的大量重復(fù),這個時候,我們可以引入布局的方式來解決這個問題。我們在layout目錄下新建一個布局文件title.xml,代碼如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"><Buttonandroid:id="@+id/title_back"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_margin="5dp"android:background="#000"android:text="Back"android:textColor="#f00"/><TextViewandroid:id="@+id/title_text"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_weight="1"android:gravity="center"android:background="#000"android:text="Title Text"android:textColor="#f5f"android:textSize="24sp"/><Buttonandroid:id="@+id/title_edit"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_margin="5dp"android:background="#000"android:text="Edit"android:textColor="#f00"/> </LinearLayout>我們在LinearLayout中分別加入了兩個Batton和一個TextView,左邊的Button可用于返回,右邊的Button可用于編輯,中間的TextView則可以用來顯示一段標題文本。熟悉一下屬性,其中android:backgroud用于為布局或控件指定一個背景,可以使用顏色或者是照片來進行填充。
另外在兩個Button中我們都使用了android:layout_margin這個屬性,它可以指定控件在上下左右方向上偏移的距離,當(dāng)然也可以使用android:layout_marginLeft或者android:layout_marginTop等屬性來單獨指定控件在某個方向上偏移的距離。
那么標題欄文件title.xml我們已經(jīng)編寫完成,那我們?nèi)绾卧诔绦蛑惺褂眠@個標題欄呢,修改acticity_main.xml中的代碼,如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.uicustomviews.MainActivity"> <include layout="@layout/title"/></LinearLayout>我們只需要通過一行include語句將標題欄布局引進來就可以了。
但是最后,不要忘了在MainActivity中將系統(tǒng)自帶的標題欄隱藏掉,代碼如下:
package com.example.uicustomviews;import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.os.Bundle;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main); ActionBar actionBar = getSupportActionBar();if(actionBar != null){actionBar.hide();}} }我們調(diào)用了getSupportActionBar()方法來獲得ActionBar的實例,然后再調(diào)用ActionBar的hide()方法將標題欄隱藏起來。
使用這種方式,不管有多少布局需要標題欄,只需要一行include語句就可以了。
測試用例如下:
2、創(chuàng)建自定義組件
引入布局的技巧確實解決了重復(fù)編寫布局代碼的問題,但是如果布局中有一些控件要求能夠響應(yīng)事件,我們還是需要在每個活動中為這些控件單獨編寫一次事件注冊的代碼。比如說,標題欄的返回按鈕,不管在哪一個活動中,都是用來銷毀當(dāng)前活動。為了不增加重復(fù)代碼,我們使用自定義控件的方式來解決。
新建TitleLayout繼承自LinearLayout,讓它成為我們自定義的標題欄控件,代碼如下:
package com.example.uicustomviews;import android.content.Context; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.AttributeSet; import android.view.LayoutInflater; import android.widget.LinearLayout;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ActionBar actionBar = getSupportActionBar();if(actionBar != null){actionBar.hide();}}public class TitleLayout extends LinearLayout {public TitleLayout(Context context, AttributeSet attrs) {super(context, attrs);LayoutInflater.from(context).inflate(R.layout.title, this);}} }我們重寫了LinearLayout中帶有兩個參數(shù)的構(gòu)造函數(shù),在布局文件中引入TitleLayout控件就會調(diào)用這個構(gòu)造函數(shù),然后在構(gòu)造函數(shù)中需要對標題進行動態(tài)加載,這就是要LayoutInflator來實現(xiàn)了。通過LayoutInflator的from()方法可以構(gòu)建出一個LayoutInflater對象,然后調(diào)用inflator()方法就可以動態(tài)加載一個布局文件,inflate()接收兩個參數(shù),第一個參數(shù)是要加載的布局文件的id,我們傳入的是R.layout.title,第二個參數(shù)是給加載好的布局再添加一個父布局,我們指定為TitleLayout,于是直接傳入this。
現(xiàn)在自定義控件已經(jīng)建好,3、我們還需要在布局文件中添加這個自定義控件,修改activity_main.xml中的代碼,如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" ><com.example.uicustomviews.TitleLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout>重新運行程序!
為標題欄的按鈕注冊點擊事件,修改TitleLayout中的代碼,如下:
首先通過findViewById()方法得到按鈕的實例,然后分別調(diào)用setOnClickListener()方法給兩個按鈕注冊了點擊事件,當(dāng)點擊返回按鈕時,銷毀當(dāng)前的活動,當(dāng)點擊編輯按鈕時彈出一段文本。
效果如下圖:
總結(jié)
以上是生活随笔為你收集整理的Android 第八课 创建自定义控件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐参考文献元数据挖掘的几篇论文
- 下一篇: Android 第九课 常用控件---