在Android的开发中,不可避免的需要用到列表嵌套列表的需要,如recycleView嵌套recylerView,我们就会发现被嵌套的列表会出现滑动冲
在滑动子rv的时候无响应(父rv上下滑动 子rv横向滑动),很明显子布局也应该是能滑动的 , 但是你在滑动子布局的时候确实父布局在滑动 这 就是 滑动冲突
事件分发机制
要向解决滑动冲突问题让子布局正常使用我们需要先了解一下Android的事件分发机制
点击事件的传递规则
首先我们要明白我们分析的对象是MotionEvent,即点击事件
点击事件就是手指接触屏幕后所产生的一系列事件:
- ACTION_DOWN 手指刚接触屏幕
- ACTION_MOVE 手指在屏幕上移动
- ACTION_UP 手指从屏幕上松开那一瞬间
所谓点击事件的分发,其实就是对MotionEvent事件的分发过程,即当一个MotionEvent产生之后,系统需要把这个事件传递给一个具体的View,而这个传递就是分发过程。
下面来介绍下点击事件分发3个很重要的方法:
public boolean dispatchTouchEvent(MotionEvent ev)
用来进行事件的分发。如果事件能够传递给当前View,那么此方法一定会被调用,返回的结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法影响,表示是否消耗当前事件。
public boolean onInterceptTouchEvent(MotionEvent ev)
在dispatchTouchEvent(MotionEvent ev)方法内部调用,用来判断是否拦截某个事件,那么在同一个事件系列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件。
public boolean onTouchEvent(MotionEvent ev)
在dispatchTouchEvent(MotionEvent ev)方法中调用,用来处理点击事件,返回的结果表示是否消耗当前事件,如锅不消耗,这在同一个事件系列中,当前View无法再接收到事件。
通过事件分发规则我们知道,OnTouchListener优先级很高,可以通过这个来告诉父布局,不要拦截我的事件
KT代码
holder.recyclerView.setOnTouchListener { v, event ->
when(event.action){
//当用户按下的时候,我们告诉父组件,不要拦截我的事件(这个时候子组件是可以正常响应事件的),拿起之后就会告诉父组件可以阻止。
MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE -> v.parent.requestDisallowInterceptTouchEvent(true)
MotionEvent.ACTION_UP -> v.parent.requestDisallowInterceptTouchEvent(false)
}
false}
java
holder.designShowRv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
ViewGroup viewGroup = (ViewGroup) view.getParent();
switch (motionEvent.getAction()){
default:break;
case MotionEvent.ACTION_UP:viewGroup.requestDisallowInterceptTouchEvent(false);break;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:viewGroup.requestDisallowInterceptTouchEvent(true);break;
}
return false;
}
});
getParent().requestDisallowInterceptTouchEvent(true)剥夺父view 对touch 事件的处理权