自定義View總結

一. 自定義ViewGroup
1.. 自定義ViewGroup必須重寫onMeasure(int widthMeasureSpec, int heightMeasureSpec):
a). 這是因爲ViewGroup是abstract的,每個viewGroup都有自己的佈局方式,因此無法像view一樣給出統一的實現方式;
b). 另外,必須實現,是因爲只有實現了此方法,其parentView才能根據其測量值來對他layout;
c). 實現方式是,利用ViewGroup提供的getChildCount(), getChildAt(), MeasureChildren得到所有child的測量值,然後根據child的getMeasuredWidth(), getMeasuredHeight()來根據自己的佈局邏輯得到自身的測量值.
d). 得到測量值後的範圍一般要在Parent給傳進來的MeasureSpec範圍內, 即parent告訴你我就給你這麼點空間,你看着辦,只能少,不能多。
e). 測量完畢後必須調用setMeasuredDimension()方法,否則無法通知Parent自己的測量值是多少。

2.. 重點是重寫onLayout(changed, l, t, r, b)方法, 即爲其每一個chlid擺放在正確的位置上!
a). 參數l, t, r, b都是都是Parent傳進來的,表示ViewGroup自身的的左上角爲在Parent中的相對位置。
b). 這個方法目的是爲了把其每一個子child放置在此座標系的哪個位置上,最終都是爲了調用child.layout(l, t, r, b)!
c). 當然也利用了ViewGroup提供的方法來實現,同1-c).

二. 自定義View
1. onMeasure(),對於view來說需要關注AT_MOST的mode情況的處理。
2. onLayout(),對於view來說不存在,也無需再管。
3. onDraw(), 是view的重點,主要是對canvas的操作,必須熟悉。

上面均需要了解自定義view的xml,style, attrs的一些細節,以及對於margin, padding的一些處理,這裏不做表述!

另外有一些其他需要注意的:
1. getMeasuredWidth()獲取的是view原始的大小,也就是這個view在XML文件中配置或者是代碼中設置的大小。getWidth()獲取的是這個view最終顯示的大小,這個大小有可能等於原始的大小也有可能不等於原始大小。
2. View的生命週期是 createView->onInflateFinished()->onAttachToWindow()->onMeasure->onSizeChanged->onLayout->onDraw->onDetachFromWindow.
3. canvas save 的是 canvas當時的大小,角度,座標系(clip不會改變座標系), restore會把棧頂的狀態pop出來,然後每次canvas.drawXX時都是產生一個全新的畫布(即上面什麼都沒有,canvas狀態和目前restore出來的一樣,包括裁剪的大小,座標系,角度),然後在上面畫,畫完貼到window上,和原有畫的圖複合。

事件傳遞機制:
View
dispatchTouchEvent : YES
onInterceptTouchEvent:NO
onTouchEvent:YES (一般return false)

ViewGroup
dispatchTouchEvent : YES
onInterceptTouchEvent:return false
onTouchEvent:繼承View

YES表示有自己的實現方法,NO表示沒有此方法,由此可見ViewGroup默認是不攔截事件的,當你自定義的ViewGroup需要攔截此事件時,那麼你需要override此方法,然後再override onTouchEvent裏實現你自己想要的效果。

// dispatchTouchEvent本身的返回值表示此ViewGroup所代表的區域是否要消耗此事件,如果true,則此後續的事件序列也會傳給它;否則後續事件不會再傳給它;
public boolean dispatchTouchEvent(){
    // 先看自己是否能消耗此事件,則後續事件序列會給它自身
    if(onInterceptTouchEvent() && onTouchEvent())
        return true;
    else // 否則,看看其子view是否有能消耗此事件
        return child.dispatchTouchEvent();
}

注意如果只是想點擊一下的效果,可以直接調用performClick()。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章