一、概述
Android SDK為我們提供了一套完整的組件庫,當這些原生的組件滿足不了我們的需求,就需要自定義組件了.
學(xué)習(xí)自定義組件最好的方式是閱讀源碼,最權(quán)威的自然是Google提供的API Demos,這里面包含了開發(fā)的各種知識,然后就是Githup上優(yōu)秀的開源項目,這些開源項目會給我們提供不同的思路,不管是簡單的組件還是復(fù)雜的組件,都是有規(guī)律的,通過閱讀優(yōu)秀的源碼,了解別人的思維模式和編程技巧,有時候你會豁然開朗.
二、分類
1、View分類
View類是Android中所有組件的基類,也就是老祖宗,其它的組件都是View的子孫,View類還有一個重要的子類:ViewGroup類,ViewGroup通常作為其它組件的容器使用.
Android中所有UI組件都是建立在View、ViewGroup基礎(chǔ)之上,對于一個Android應(yīng)用的用戶界面來說:ViewGroup作為容器來盛放其它組件,ViewGroup里面除了可以盛放普通View組件之外,還可以再次盛放ViewGroup,下圖顯示一個用戶界面的組件層次.
2、自定義組件分類
一般來說,有4種方式用來實現(xiàn)自定義組件:
(1)繼承View類
這種方式基本是從零開始自定義了,工作量比較大
(2)繼承View子類(非ViewGroup)
比如繼承TextView、ImageView
(3)繼承ViewGroup類
這里ViewGroup包括ViewGroup的子類,像我們最常用的LinearLayout、RelativeLayout
(4)自定義組合控件
將多個已有組件組合形成一個新的組件
三、構(gòu)造方法
public class XView extends View {
/**
* 含1個參數(shù)的構(gòu)造方法
*/
public XView(Context context) {
super(context);
}
/**
* 含2個參數(shù)的構(gòu)造方法
*/
public XView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 含3個參數(shù)的構(gòu)造方法
*/
public XView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 含4個參數(shù)的構(gòu)造方法(API>=21)
*/
public XView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
}
學(xué)習(xí)一個類是從構(gòu)造方法開始,自定義組件也是如此.
自定義組件一共4個構(gòu)造方法:
1、第一個構(gòu)造方法:只有1個參數(shù)context,在代碼中創(chuàng)建組件時會調(diào)用該構(gòu)造,比如在Activity中:
XView xView = new XView(this);
2、第二個構(gòu)造方法:有2個參數(shù),在layout布局文件中使用時會調(diào)用該構(gòu)造,比如:
<com.fgq.demo.XView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
PS:在布局文件中使用自定義組件的寫法:完整包名+類名
參數(shù)attrs表示當前配置的屬性集,在布局文件中定義的寬、高等屬性都包含在attrs中.
3、第三個構(gòu)造方法:有3個參數(shù),這個構(gòu)造方法系統(tǒng)不會調(diào)用,一般在有自定義屬性時,我們會在第二個構(gòu)造方法中手動調(diào)用該構(gòu)造.
4、第四個構(gòu)造方法:這個構(gòu)造在API>=21(5.0)才能使用,除非你的minSdkVersion>=21,不然不會用到.
所以自定義組件構(gòu)造方法最常見的寫法像下面這樣:
public XView(Context context) {
this(context, null);
}
public XView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public XView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
四、onMeasure、onDraw
在了解完構(gòu)造方法之后就要介紹兩個方法:onMeasure、onDraw,自定義View大部分時候需要重寫這兩個方法:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
1、onMeasure
onMeasure方法用來測量組件的大小,在Android中,組件的大小都是通過該方法進行測量,不管界面多么復(fù)雜,每個組件都負責(zé)計算自己的大小,如果不重寫該方法,父類View會有默認的實現(xiàn).
那么為什么要重寫該方法?我們在xml布局文件中不是設(shè)置了寬、高了嗎?
在初學(xué)Android時,我們就知道:在xml布局文件中,layout_width、layout_height是可以不用寫具體尺寸的,比如寬高都設(shè)置為wrap_content(包裹內(nèi)容),此時并沒有指定組件的真正大小,但是繪制到屏幕上的View必須要有具體的寬高,所以我們需要重寫onMeasure自己去測量寬高.
當然,對于測量組件大小,父類View有默認的處理,但是如果默認處理滿足不了我們的需求,此時就需要重寫onMeasure方法了.
2、onDraw
這個方法我們應(yīng)該很熟悉了,在Graphics2D API一章中我們一直在重寫該方法,該方法用來繪制組件的內(nèi)容.