滑動衝突
顧名思義,即爲子佈局與父佈局同時可滑動時可能造成的一種衝突情況,一般主要分爲一下兩種類型
- 外部佈局與內部佈局滑動方向不一致,例如ScrollView嵌套ViewPager
- 外部佈局與內部佈局滑動方向一致,例如ScrollView嵌套ListView,ViewPager嵌套ViewPager
要想了解滑動衝突的根本原因和解決辦法,我們先了解一下Android的事件分發機制
觸摸事件產生
Android整個觸摸事件產生過程可以分爲 linux層 ==> native層 ==> java層
linux層:
由於Android底層是linux,所以Android也是採取跟linux相同的方式處理用戶輸入事件,那就是中斷的方式。當用戶觸摸到屏幕是,觸摸屏會產生相應的中斷,並由其驅動程序處理該中斷,最終將採集到的數據處理之後存放進了對應的/dev/input/eventX文件中
native層:
native層對於觸摸事件主要靠三個組件,分別是EventHub,InputReader,InputDispatcher。
EventHub主要負責監聽讀取/dev/input目錄下產生的事件,並封裝成RawEvent結構給InputReader
InputReader從EventHub那獲取事件信息後轉化成EventEntry事件加入到InputDispatcher的mInboundQueue隊列中
InputDispatcher最終從mInboundQueue隊列取出事件,轉化爲DispatchEntry事件加入到Connection的outboundQueue隊列,然後使用InputChannel利用socket跨進程通信的原理分發事件到java層,這個暫先不討論。
Android本身主線程是默認開啓Looper不斷從MessageQueue隊列中獲取消息,但是MessageQueue創建時同樣創建了一個NativeMessageQueue隊列,用於接收native層的消息
- loop每次循環時便通過nativePollOnce方法讀取該隊列,並調用Looper.pollInner方法
- 這個方法最終又會回調NativeInputEventReceiver.handleEvent方法。
- 而在這個方法中主要又是通過調用consumeEvents方法進行事件處理。
- consumeEvents方法會產生MotionEvent對象,並通過jni的gInputEventReceiverClassInfo.dispatchInputEvent方法
- 而jni的這個方法最終就調用了java層的InputEventReceiver.dispatchInputEvent方法正式進入到java層事件分發
java層
java層通過inputEventReceiver.dispatchInputEvent方法最終調用Activity.dispatchTouchEvent進入到Android事件分發機制之中
事件分發
Mark一下 Android事件分發機制詳解