Android自定義View—事件分發機制與滑動衝突處理(三)

View的事件分發機制,其實就是對MotionEvent事件的分發機制,即當一個MotionEvent產生了之後,系統須要把這個事件傳遞給一個具體的View,這個傳遞的過程就是分發過程。spa

一.View的事件分發機制.net

總體流程:blog

dispatchTouchEvent()—>onTouch()—>onTouchEvent()—>onClick()事件

dispatchTouchEvent():View事件分發的入口,返回值表示MotionEvent是否被消費。圖片

onTouch():View須要處理事件時,若是它設置了onTouchListener,那麼onTouchListener中的onTouch方法會被調用。若是onTouch方法返回false,那麼View的onTouchEvent()方法會被調用;若是onTouch方法返回true,那麼View的onTouchEvent()方法將不會被調用。onTouch()的優先級比onTouchEvent()的優先級更高。get

onTouchEvent():View自身對於Touch處理的實現 ,返回結果表示是否消耗當前事件。it

onClick() : View的onTouchEvent()的優先級比onClick()高,用於處理clickListener設置的點擊事件。io

二.ViewGroup的事件分發機制容器

總體流程:cli

這裏寫圖片描述

圖片來自 谷歌的小弟

當一個點擊事件產生之後,它的傳遞過程遵循以下順序:Activity—>Window—>外層ViewGroup。 外層ViewGroup接收到事件之後,就會按照事件分發機制去分發事件。若是這個ViewGroup的onInterceptTouchEvent()方法返回true,就表示它要攔截當前事件,接着事件就會交給這個ViewGroup來處理;若是這個ViewGroup的onInterceptTouchEvent()方法返回false,就表示它不攔截當前事件,接着事件就會交給它的子元素來處理。若是一個View的onTouchEvent()返回false,那麼它的父容器的onTouchEvent()就會被調用。以此類推,若是全部的元素都不處理這個事件,那麼這個事件最終會傳遞給Activity處理,即Activity的onTouchEvent()方法會調用。

三.相關知識點

1.同一個事件序列是指從手指接觸屏幕的那一刻起,到手指離開屏幕的那一刻結束,在這個過程當中所產生的一系列事件,這個事件序列以down事件開始,中間含有不定量的move事件,最終以up事件結束。

2.某個View一旦決定攔截,那麼這一事件序列都只能由它來處理(若是事件序列可以傳遞給它的話),而且它的onInterceptTouchEvent()不會再被調用,這是由於系統會將同一事件序列內的其餘方法都交給他處理。

3.某個View一旦開始處理事件,若是它不消耗ACTION_DOWN事件(onTouchEvent方法返回了false),那麼同一事件序列中的其餘事件都不會交給它來處理,而且事件將從新交給它的父元素處理,即父元素的onTouchEvent會被調用。

4.ViewGroup默認不攔截任何事件,即默認onInterceptTouchEvent返回false。View沒有onInterceptTouchEvent方法,一旦有事件傳遞給它,它的 
onTouchEvent方法就會調用。

5.事件傳遞過程是由外向內的,即事件老是先傳遞給父元素,而後再由父元素分發給子View,經過requestDisallowInterceptTouchEvent方法能夠在子元素中干預父元素的分發過程,可是ACTION_DOWN事件除外。

四.滑動衝突的處理

  1. 內部攔截法:子View禁止父View攔截Touch事件 
    內部攔截法是指父容器不攔截任何事件,全部的事件都傳遞給子元素,若是子元素須要此事件就直接消耗掉,不然就交給父容器處理。讓子View調用requestDisallowInterceptTouchEvent( )禁止父View對Touch的攔截便可,這樣就能夠解決滑動衝突的問題。

  2. 外部攔截法:父View中準確地進行事件分發和攔截  外部攔截法是指點擊事件都先通過父容器攔截處理,若是父容器須要此事件就攔截,若是不須要就不攔截。咱們能夠重寫父View中與Touch事件分發相關的方法—–onInterceptTouchEvent( )來進行處理,這樣就能夠解決滑動衝突的問題。

相關文章
相關標籤/搜索