? ? ?首先聋溜,本文不會涉及完全理論性的關于事件分發(fā)的講解锯厢,而是將一部分理論應用到該實例中皮官。因為事件分發(fā)理論太多、太復雜哲鸳,如果不是處理很復雜的自定義View臣疑,只需要用到其中一小部分就可以完成任務了,對此徙菠,我們必須:
從理論中來,到實踐中去
為什么重寫dispatchTouchEvent()
? ? ?在寫自定義View的時候郁岩,一旦涉及到事件分發(fā)婿奔,往往會重寫onTouchEvent()缺狠,而這里卻是重寫了dispatchTouchEvent(),為什么呢?要回答這個問題萍摊,就必須說明dispatchTouchEvent()是干什么的挤茄。
? ? ?當事件到達View時,如果他是個普通的View,則沒有必要去分發(fā)事件冰木,直接調(diào)用到onTouchEvent來決定是否要處理該事件穷劈;如果他是個ViewGroup,那么他就必須調(diào)用dispatchTouchEvent()把事件分發(fā)下去踊沸,只有當ViewGroup主動攔截了事件,或者所有的子孩子都不處理這個事件歇终,該事件才會傳遞到他的onTouchEvent()方法。
? ? ?在該例子中逼龟,PtrFrameLayout必須決定事件是自己處理(調(diào)用scroll方法),還是傳遞給子孩子(調(diào)用super.dispatchTouchEvent()评凝。試想,如果我們重寫的是onTouchEvent,而且content是一個ScrollView,那么所有的事件都會被ScrollView拿到(除非攔截,那樣又增加了復雜度)腺律。所以奕短,必須在分發(fā)的時候就要做出判斷。
DOWN事件的處理
問題:為什么不能直接返回super.dispatchTouchEvent()?
? ? ?如果content是原生控件,沒有設置clickListener匀钧,也沒有重寫ouTouch等翎碑,反正就是他不會處理任何事件。如普通的LinearLayout,他會所有事件的處理都是返回false之斯,也就是告訴父控件--事件給你吧杈女,我統(tǒng)統(tǒng)不要。那么吊圾,PtrFrameLayout的dispatchTouchEvent()也就返回false达椰,也就是告訴他的父控件,后面的事件我也不care了项乒,你就不要傳遞給我了啰劲。所以,后面的MOVE事件他也就接受不到了檀何,此時控件也就滑不動了蝇裤。
問題:為什么要把DOWN事件傳遞給子視圖?
? ? ?如果一個視圖沒有拿到DOWN事件频鉴,那么后續(xù)的事件他也就都拿不到了栓辜。因為父視圖不把DOWN事件往下傳遞,也就是說垛孔,后面的事件我自己都要了藕甩。
問題:正確的處理方式是怎樣?
? ? ?首先,我們要確保PtrFrameLayout無論如何都要拿到事件周荐,對于子孩子能處理的事件狭莱,給子孩子處理僵娃,而子孩子不能處理的,則自己處理腋妙。所以默怨,在DOWN事件中,事件要先交給子視圖骤素,無論子視圖怎么處理匙睹,父視圖返回true,表示事件已經(jīng)處理济竹,那么后續(xù)的MOVE事件還是會先到父視圖來痕檬,而且當父視圖再次調(diào)用super.dispatchTouchEvent()把消息往下傳遞時,子視圖也能收到MOVE事件规辱,從而實現(xiàn)content(如ScrollView)的滑動谆棺。
MOVE事件的處理
? ? 在滑動過程中,有時候是content滑動罕袋,有時候是PtrFrameLayout調(diào)用scroll方法執(zhí)行滑動改淑。如果想讓content滑動,直接調(diào)用super.dispatchTouchEvent()浴讯,事件會傳遞給content朵夏,他會自己處理事件;如果想讓PtrFrameLayout滑動榆纽,調(diào)用scroll方法后仰猖,返回true即可,代表事件已經(jīng)處理奈籽。