天天看點

安卓View和ViewGroup簡介UI繪制事件分發

簡介

在安卓app的頁面中,所有的界面都是由View和ViewGroup組合而成的。View其實就是繪制在螢幕上與使用者互動的對象,而ViewGroup是View的子類它可以了解成是存放其他View( ViewGroup)的容器。他們的結構如圖:

安卓View和ViewGroup簡介UI繪制事件分發

UI繪制

繪制流程:Measure(測量)——》Layout(布局)——》Draw(繪制)

安卓View和ViewGroup簡介UI繪制事件分發

onDraw用于UI重繪,onLayout則在布局發生變化時調用,onMeasure計算view對象的大小。

ps:關于過度繪制

檢測:在usb調試助手中打開GPU過度繪制的調試。

内容:藍色(一層覆寫,像素兩次繪制,大片的藍色可以接受),綠色(兩層覆寫,三次繪制,中等範圍可以接受但需要減少),淺紅色(三層覆寫,四次繪制,小範圍可以接受),深紅色(四層覆寫,五次繪制或更多,為錯誤現象必須去修正)

優化方法:減少布局層級,去除不必要的背景(或設為透明)。

事件分發

事件U型流向:Activity---->ViewGroup—>(調用dispatchTouchEvent)View–>( 調用onTouchEvent)ViewGroup—>Activity。

當然,這是在沒有重寫控件(view)方法和改變傳回值而是直接用super調用父類的預設實作 的情況下,即return super.xxxxx()。

而事實上,從Activity開始向下分發事件,隻有傳回super.dispatchTouchEvent(ev)才會往下分發到ViewGroup,否則無論傳回True或False都不會再繼續往下分發。

然後是ViewGroup的事件分發,ViewGroup也是隻有當dispatchTouchEvent傳回super.dispatchTouchEvent(ev)時才會繼續向子View分發,如果傳回false則向上将事件交由Activity的onTouchEvent處理,傳回true則終止分發事件走到盡頭,而ViewGroup自己有一個onInterceptTouchEvent方法,這個方法是用來攔截事件給自己處理的,該方法傳回true就可以将事件傳遞到ViewGroup的onTouchEvent方法中,傳回false或者super.onInterceptTouchEvent都表示不攔截繼續往子View傳遞。

最後事件總算到達View這邊,子View的dispatchTouchEvent方法和ViewGroup類似:如果傳回true那麼就終止事件分發,傳回false則是向上交由ViewGroup處理即分發到ViewGroup的onTouchEvent中。而view沒有onInterceptTouchEvent方法,是以要想自己處理該事件,則傳回super.dispatchTouchEvent(ev)即可(調用super.dispatchTouchEvent預設将事件分發到自身的onTouchEvent中)。

貼出一張來自其它部落格中的圖,标出圖中的super可以發現隻要傳回父類的預設實作(super.xxx()),就會一直按照先向下分發一直到某個葉子view結點才向上回溯一直到Activity的onTouchEvent方法。向下的過程中,dispatchEvent傳回true事件就認為被消費,傳回false會停止分發并向上回溯到父控件的onTouchEvent中;向上的過程中,onTouchEvent傳回true則表示事件被消費了,傳回false(或者super.onTouchEvent)則繼續向上回溯。

安卓View和ViewGroup簡介UI繪制事件分發

最後再總結一下事件分發的内容:首先Activity的dispatchTouchEvent傳回true或false都會結束事件分發,隻有傳回super.dispatchTouchEvent才會将事件分發到ViewGroup的dispatchTouchEvent;對于ViewGroup的dispatchTouchEvent傳回true則事件分發終止,傳回false的話會向上分發到Activity的onTouchEvent,隻有傳回super.dispatchTouchEvent才會繼續向下分發到子View的dispatchTouchEvent;不過在此之前還會有一個ViewGroup的攔截器的判斷,如果onInterceptTouchEvent的傳回值為true,則事件将被攔截到ViewGroup自己的onTouchEvent,除此之外無論傳回false還是super.onInterceptTouchEvent都将不會攔截事件,事件會繼續向子View分發;最後就是View的dispatchTouchEvent,傳回true則事件終止分發認為被消費,傳回false事件會向上回溯到ViewGroup的onTouchEvent中,而傳回super.dispatchTouchEvent則表示自己消費該事件。