前两篇文章:
可能是最详细的Android点击事件处理详解
可能是最详细的Android点击事件处理详解(二)
这里再次延伸一下,在ScrollView和RecyclerView嵌套中touch事件的传递过程,以及嵌套滑动冲突的问题。
如上图,外层是一个NestedScrollView,上半部分是一个400dp的RecyclerView。下面是用来填充的一些TextView。
本篇主要分四块来讲述:
日志如下:
TouchScrollViewActivity[dispatchTouchEvent, 64]: ACTION_DOWN
NormalScrollView[dispatchTouchEvent, 35]: ACTION_DOWN
NormalScrollView[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalRecyclerView[dispatchTouchEvent, 36]: ACTION_DOWN
NormalRecyclerView[onInterceptTouchEvent, 63]: ACTION_DOWN
NormalView[dispatchTouchEvent, 84]: ACTION_DOWN
NormalView$2[onTouch, 57]: ACTION_DOWN
NormalView[onTouchEvent, 111]: ACTION_DOWN
TouchScrollViewActivity[dispatchTouchEvent, 68]: ACTION_MOVE
NormalScrollView[dispatchTouchEvent, 39]: ACTION_MOVE
NormalScrollView[onInterceptTouchEvent, 65]: ACTION_MOVE
NormalRecyclerView[dispatchTouchEvent, 40]: ACTION_MOVE
NormalRecyclerView[onInterceptTouchEvent, 67]: ACTION_MOVE
NormalView[dispatchTouchEvent, 96]: ACTION_CANCEL
NormalView$2[onTouch, 68]: ACTION_CANCEL
NormalView[onTouchEvent, 122]: ACTION_CANCEL
TouchScrollViewActivity[dispatchTouchEvent, 68]: ACTION_MOVE
NormalScrollView[dispatchTouchEvent, 39]: ACTION_MOVE
NormalScrollView[onInterceptTouchEvent, 65]: ACTION_MOVE
NormalRecyclerView[dispatchTouchEvent, 40]: ACTION_MOVE
NormalRecyclerView[onTouchEvent, 94]: ACTION_MOVE
TouchScrollViewActivity[dispatchTouchEvent, 68]: ACTION_MOVE
NormalScrollView[dispatchTouchEvent, 39]: ACTION_MOVE
NormalRecyclerView[dispatchTouchEvent, 40]: ACTION_MOVE
NormalRecyclerView[onTouchEvent, 94]: ACTION_MOVE
TouchScrollViewActivity[dispatchTouchEvent, 72]: ACTION_UP
NormalScrollView[dispatchTouchEvent, 42]: ACTION_UP
NormalRecyclerView[dispatchTouchEvent, 43]: ACTION_UP
NormalRecyclerView[onTouchEvent, 97]: ACTION_UP
首先说下一下只有400dp高度的RecyclerView在滑动的时候是有Fling效果的。因为高度的限定,焦点在RecyclerView内,而且RecyclerView是可以滑动的,此时虽然ScrollView也是可以滑动,但是优先处理内部滑动,并且也有Fling效果,不存在冲突问题。因为系统已经帮我们处理了。
从日志看跟我们可能是最详细的Android点击事件处理详解(二)
中滑动日志是一样的。只不过又多了一层ScrollView而已。这里不做过多描述,重点在于此时的RecyclerView有Fling效果。
日志如下:
TouchScrollViewActivity[dispatchTouchEvent, 64]: ACTION_DOWN
NormalScrollView[dispatchTouchEvent, 35]: ACTION_DOWN
NormalScrollView[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 84]: ACTION_DOWN
NormalView$2[onTouch, 57]: ACTION_DOWN
NormalView[onTouchEvent, 111]: ACTION_DOWN
TouchScrollViewActivity[dispatchTouchEvent, 68]: ACTION_MOVE
NormalScrollView[dispatchTouchEvent, 39]: ACTION_MOVE
NormalScrollView[onInterceptTouchEvent, 65]: ACTION_MOVE
NormalView[dispatchTouchEvent, 89]: ACTION_MOVE
NormalView$2[onTouch, 61]: ACTION_MOVE
NormalView[onTouchEvent, 115]: ACTION_MOVE
TouchScrollViewActivity[dispatchTouchEvent, 68]: ACTION_MOVE
NormalScrollView[dispatchTouchEvent, 39]: ACTION_MOVE
NormalScrollView[onInterceptTouchEvent, 65]: ACTION_MOVE
NormalView[dispatchTouchEvent, 96]: ACTION_CANCEL
NormalView$2[onTouch, 68]: ACTION_CANCEL
NormalView[onTouchEvent, 122]: ACTION_CANCEL
TouchScrollViewActivity[dispatchTouchEvent, 68]: ACTION_MOVE
NormalScrollView[dispatchTouchEvent, 39]: ACTION_MOVE
NormalScrollView[onTouchEvent, 92]: ACTION_MOVE
TouchScrollViewActivity[dispatchTouchEvent, 72]: ACTION_UP
NormalScrollView[dispatchTouchEvent, 42]: ACTION_UP
NormalScrollView[onTouchEvent, 95]: ACTION_UP
首先描述一下此时的手指焦点是在ScrollView下面的View上面的此时滑动的是ScrollView是有Fling效果的。
从日志看跟我们可能是最详细的Android点击事件处理详解(二)
中滑动日志是一样的。只不过是将RecyclerView换成了ScrollView。这里不做过多描述,重点在于此时的ScrollView有Fling效果。因为内部的View不具备滑动效果。不存在冲突。
日志如下:
TouchScrollViewActivity[dispatchTouchEvent, 64]: ACTION_DOWN
NormalScrollView[dispatchTouchEvent, 35]: ACTION_DOWN
NormalScrollView[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalRecyclerView[dispatchTouchEvent, 36]: ACTION_DOWN
NormalRecyclerView[onInterceptTouchEvent, 63]: ACTION_DOWN
NormalView[dispatchTouchEvent, 84]: ACTION_DOWN
NormalView$2[onTouch, 57]: ACTION_DOWN
NormalView[onTouchEvent, 111]: ACTION_DOWN
TouchScrollViewActivity[dispatchTouchEvent, 68]: ACTION_MOVE
NormalScrollView[dispatchTouchEvent, 39]: ACTION_MOVE
NormalScrollView[onInterceptTouchEvent, 65]: ACTION_MOVE
NormalRecyclerView[dispatchTouchEvent, 40]: ACTION_MOVE
NormalRecyclerView[onInterceptTouchEvent, 67]: ACTION_MOVE
NormalView[dispatchTouchEvent, 96]: ACTION_CANCEL
NormalView$2[onTouch, 68]: ACTION_CANCEL
NormalView[onTouchEvent, 122]: ACTION_CANCEL
TouchScrollViewActivity[dispatchTouchEvent, 68]: ACTION_MOVE
NormalScrollView[dispatchTouchEvent, 39]: ACTION_MOVE
NormalScrollView[onInterceptTouchEvent, 65]: ACTION_MOVE
NormalRecyclerView[dispatchTouchEvent, 40]: ACTION_MOVE
NormalRecyclerView[onTouchEvent, 94]: ACTION_MOVE
TouchScrollViewActivity[dispatchTouchEvent, 72]: ACTION_UP
NormalScrollView[dispatchTouchEvent, 42]: ACTION_UP
NormalScrollView[onInterceptTouchEvent, 69]: ACTION_UP
NormalRecyclerView[dispatchTouchEvent, 43]: ACTION_UP
NormalRecyclerView[onTouchEvent, 97]: ACTION_UP
此时的滑动日志其实和RecyclerView限制高度。滑动RecyclerView的日志一样,但是因为此时的ScrollView内部只有一个RecyclerView此时的ScollView和RecyclerView高度其实是一样的。此时系统在滑动处理的时候,没有帮助我们处理,此时滑动的时候从日志看是作用到内部的RecyclerView了,但是此时的RecyclerView没有Fling效果,即快速上滑屏幕,RecyclerView只会动一点,而不是惯性滚动很多。
对于这种情况其实很好解决,因为ScrollView和RecyclerView高度一样。滑动内层和外层都是可以的。而一般处理冲突在外层处理比较方便一点。这里又三种处理方式。
以上三种方法均是屏蔽内层的滑动,让外层进行滑动。
首先我们知道,单独滑动ScrollView和RecyclerView都是可以有Fling效果的,但是当RecyclerView和ScrollView同时滑动的时候,就不行了。这个时候我们要做的就是区分他们的滑动,因为系统以及帮我们处理了一部分。我们需要做的只是在临界点去让他们分别滑动。
提供如下思路:
思路是这样的。肯定可以。只不过有一些细节需要处理。代码后续我会补上。
项目源码: https://github.com/wangxp423/ViewExercise
在,首页 -> Touch事件研究中。