滑动冲突
顾名思义,即为子布局与父布局同时可滑动时可能造成的一种冲突情况,一般主要分为一下两种类型
- 外部布局与内部布局滑动方向不一致,例如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事件分发机制详解