1. 程式人生 > >ScrollView 巢狀ViewPager滑動衝突解決

ScrollView 巢狀ViewPager滑動衝突解決

這篇部落格主要講解一下幾個問題

  • 粗略地介紹一下View的事件分發機制
  • 解決事件滑動衝突的思路及方法
  • ScrollView 裡面巢狀ViewPager導致的滑動衝突
  • ViewPager裡面巢狀ViewPager 導致的滑動衝突
  • 輪播圖的幾種實現方式

先看一下效果圖

ScrollView裡面巢狀ViewPager

ViewPager裡面巢狀ViewPager

View的 事件分發機制

這篇部落格不打算詳細講解View的事件分發機制,因為網上已經出現了一系列的好 文章,我自己的水平也有限,目前肯定寫得不咋的。

先囉嗦一下,View 的事件分發機制主要涉及到一下三個 方法

  • dispatchTouchEvent ,這個方法主要是用來分發事件的
  • onInterceptTouchEvent,這個方法主要是用來攔截事件的(需要注意的是ViewGroup才有這個方法,View沒有onInterceptTouchEvent這個方法
  • onTouchEvent 這個方法主要是用來處理事件的
  • requestDisallowInterceptTouchEvent(true),這個方法能夠影響父View是否攔截事件,true 表示父 View 不攔截事件,false 表示父 View 攔截事件

  • 仔細看的話,圖分為3層,從上往下依次是Activity、ViewGroup、View
  • 事件從左上角那個白色箭頭開始,由Activity的dispatchTouchEvent做分發
  • 箭頭的上面字代表方法返回值,(return true、return false、return super.xxxxx(),super 的意思是呼叫父類實現。
  • dispatchTouchEvent和 onTouchEvent的框裡有個【true—->消費】的字,表示的意思是如果方法返回true,那麼代表事件就此消費,不會繼續往別的地方傳了,事件終止。
  • 目前所有的圖的事件是針對ACTION_DOWN的,對於ACTION_MOVE和ACTION_UP我們最後做分析。
  • 之前圖中的Activity 的dispatchTouchEvent 有誤(圖已修復),只有return super.dispatchTouchEvent(ev) 才是往下走,返回true 或者 false 事件就被消費了(終止傳遞)。

總結

當TouchEvent發生時,首先Activity將TouchEvent傳遞給最頂層的View,TouchEvent最先到達最頂層 view 的 dispatchTouchEvent ,然後由 dispatchTouchEvent 方法進行分發,

  • 如果dispatchTouchEvent返回true 消費事件,事件終結。
  • 如果dispatchTouchEvent返回 false ,則回傳給父View的onTouchEvent事件處理;

    onTouchEvent事件返回true,事件終結,返回false,交給父View的OnTouchEvent方法處理

  • 如果dispatchTouchEvent返回super的話,預設會呼叫自己的onInterceptTouchEvent方法

    預設的情況下interceptTouchEvent回撥用super方法,super方法預設返回false,所以會交給子View的onDispatchTouchEvent方法處理

    如果 interceptTouchEvent 返回 true ,也就是攔截掉了,則交給它的 onTouchEvent 來處理,

    如果 interceptTouchEvent 返回 false ,那麼就傳遞給子 view ,由子 view 的 dispatchTouchEvent 再來開始這個事件的分發。

關於更多詳細分析,請檢視原部落格圖解 Android 事件分發機制,真心推薦,寫得很好。