萌萌の初音
萌萌の初音
发布于 2023-06-29 / 1367 阅读
0

RecyclerView滑动事件处理SimpleOnItemTouchListener

需求

在用户上下滑动列表时,检测用户是否左右滑动,如果是左右滑动需要根据左右滑动的距离绘制当前item的显示效果,还要判断有没有超出y轴范围;

解决思路

1.在item的itemView添加onTouchListener事件,事件无法正常传递
2.使用SimpleOnItemTouchListener实现效果✅

SimpleOnItemTouchListener类的介绍

        /**
         * Silently observe and/or take over touch events sent to the RecyclerView
         * before they are handled by either the RecyclerView itself or its child views.
         *
         * <p>The onInterceptTouchEvent methods of each attached OnItemTouchListener will be run
         * in the order in which each listener was added, before any other touch processing
         * by the RecyclerView itself or child views occurs.</p>
         *
         * @param e MotionEvent describing the touch event. All coordinates are in
         *          the RecyclerView's coordinate system.
         * @return true if this OnItemTouchListener wishes to begin intercepting touch events, false
         * to continue with the current behavior and continue observing future events in
         * the gesture.
         *
         * 在RecyclerView本身或其子视图处理发送到RecyclerView的触摸事件之前,静默地观察和/或接管这些事件。
         * 在RecyclerView本身或子视图进行任何其他触摸处理之前,每个附加的OnItemTouchListener的onInterceptTouchEvent方法将按照添加每个侦听器的顺序运行。
         * 参数:
         * e–描述触摸事件的MotionEvent。所有坐标都在RecyclerView的坐标系中。
         * 返回:
         * 如果此OnItemTouchListener希望开始拦截触摸事件,则为true;如果为false,则继续当前行为并继续          * 观察手势中的未来事件。
         */
        boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e);

        /**
         * Process a touch event as part of a gesture that was claimed by returning true from
         * a previous call to {@link #onInterceptTouchEvent}.
         *
         * @param e MotionEvent describing the touch event. All coordinates are in
         *          the RecyclerView's coordinate system.
         *
         * 将触摸事件作为手势的一部分进行处理,该手势是通过从上一次对onInterceptTTouchEvent的调用返回true来声明的。
         * 参数:
         * e–描述触摸事件的MotionEvent。所有坐标都在RecyclerView的坐标系中。
         */
        void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e);

        /**
         * Called when a child of RecyclerView does not want RecyclerView and its ancestors to
         * intercept touch events with
         * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}.
         *
         * @param disallowIntercept True if the child does not want the parent to
         *                          intercept touch events.
         * @see ViewParent#requestDisallowInterceptTouchEvent(boolean)
         *
         * 当RecyclerView的子级不希望RecyclerView及其祖先使用ViewGroup.oInterceptTouchEvent(MotionEvent)截取触摸事件时调用。
         * 参数:
         * disallowIntercept–如果孩子不希望父母拦截触摸事件,则为True。
         * 另请参阅:
         * ViewParent.requestDisableInterceptTouchEvent(布尔值)
         */
        void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept);

通过以上方法介绍我们只需要重写onInterceptTouchEvent来实现需求;

重写onInterceptTouchEvent

通过返回的MotionEvent类,我们可以跟onTouchListener一样识别用户手势,例如:MotionEvent.ACTION_MOVE、MotionEvent.ACTION_UP等,也可以获取当前的x、y轴坐标计算位移;
我们还可以通过返回的RecyclerView搭配MotionEvent来获取当前位置的itemView:

object : SimpleOnItemTouchListener() {
	override fun onInterceptTouchEvent(rv: RecyclerView, event: MotionEvent): Boolean {
    	val view = rv.findChildViewUnder(event.x, event.y) //获取当前x\y坐标的itemView
        rv.getChildAdapterPosition(view) //通过view来获取列表位置
        return super.onInterceptTouchEvent(rv, event)
    }
}

通过以上示例就可以操作获取到的view执行想要的效果实现需求了~