当前位置: 代码迷 >> 综合 >> RecyclerView嵌套RecyclerView,内层RecyclerView区域无法响应Item点击
  详细解决方案

RecyclerView嵌套RecyclerView,内层RecyclerView区域无法响应Item点击

热度:42   发布时间:2023-10-18 17:18:49.0

问题描述

项目中遇到了一个RecyclerView内嵌套RecyclerView,内层RecyclerView的区域无法响应所在Item的点击事件的问题( RecyclerView内嵌套RecyclerView导致外层item点击不响应)。

首先,需要知道触摸事件的响应机制是怎么样的:由上至下,最下层不消费后,则由下至上;然后需要了解一下这三个方法:dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent。

dispatchTouchEvent:事件分发,一般不处理,返回false,事件到onInterceptTouchEvent中处理。

onInterceptTouchEvent:事件拦截,返回true的话,则不向下传递,事件到onTouchEvent,返回false事件往下传递

onTouchEvent:返回true代表事件消费,返回false不消费,事件往上传递。

只需要内部RecyclerView用于显示,不需要任何操作的情况下,为了使外层RecyclerView的item响应,把嵌入的RecyclerView触摸事件拦截,并且不消费就行了,事件就会传递到上一层,重写嵌套的RecyclerView

解决方式(形式不同,原理相同)

方式一

 

viewHolder.rv.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {return viewHolder.itemView.onTouchEvent(event);}});

给内层的RecyclerView设置OnTouchListener,在onTouch中处理外层RecyclerView的Item的触摸事件onTouchEvent,item已经设置了点击事件,所以在onTouchEvent的事件处理中会调用到item的点击事件。

方式二

 

viewHolder.rv.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {if(event.getAction() == MotionEvent.ACTION_UP){viewHolder.itemView.performClick();}return false;}
});

依然是给内层的RecyclerView设置OnTouchListener,在onTouch中调用外层RecyclerView的Item的preformClick方法,执行外层item的点击事件。

方式三(其实就是把方式二加了些判断封装了下)

 

viewHolder.rv.setOnTouchListener(new ChildTouchListener(viewHolder.itemView));

 

public class ChildTouchListener implements View.OnTouchListener{private float downX;private float downY;private float touchSlop;private View view;public ChildTouchListener(View view){this.view = view;touchSlop = ViewConfiguration.get(view.getContext()).getScaledTouchSlop();}@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getActionMasked()){case MotionEvent.ACTION_DOWN:downX = event.getX();downY = event.getY();break;case MotionEvent.ACTION_UP:if (Math.abs(event.getY() - downY) < touchSlop && Math.abs(event.getX() - downX) < touchSlop){view.performClick();}break;}return false;}
}

依然是给内层的RecyclerView设置OnTouchListener,在onTouch中调用外层RecyclerView的Item的preformClick方法,执行外层item的点击事件,就是加了些判断。

总结

我们上面也说了,其实原理是相同的,里面的RecyclerView区域点击没响应,是因为RecyclerView内部重写了onTouchEvent方法,导致了上述问题的发生,然后我们给RecyclerView设置OnTouchListener,那么OnTouchListener中的onTouch方法会在onTouchEvent方法之前回调,并且需要注意onTouch方法的返回值,如果是false,onTouchEvent方法才会被调用,如果是true,那么onTouchEvent方法将不会被调用(也就是给view设置的OnTouchListener的优先级高于onTouchEvent),我们的处理中返回false以便不影响RecyclerView后续onTouchEvent中的固有逻辑。另外onTouchEvent方法中,如果当前View设置的有OnClickListener,那么它的onClick方法会被调用,这也就是方法1中直接调用了itemView的onTouchEvent方法,自然后续会调用到我们设置的OnClickListener中的onClick方法,执行我们想要的业务逻辑。

 

  相关解决方案