之前项目中有竖向RecyclerView的子item中嵌套横向RecyclerView,当时横向直接用了RecyclerView,虽然感觉横向的RecyclerView滑动手感不是那么好,但是只要保证手滑动的方向水平,还是可以用。但是设计不知道哪根筋搭错了,直接给了个横滑的RecyclerView嵌套横滑的RecyclerView,这下好了,不是滑动手感不好的问题,是子item里的RecyclerView直接无法滑动了。
其实无论是竖滑嵌横滑滑动手感不好还是横滑嵌横滑内部的RecyclerView无法滑动,都是触摸事件处理的问题。这就需要提供一个自定义的RecyclerView重写里面的方法来解决目前的问题。
可以先看下体验Demo:https://github.com/SunJenry/HorizontalRecyclerView,对比直接使用RecyclerView在竖向嵌套横向的时候滑动更加自然,也解决了横向嵌套横向无法滑动问题。
重点就是下面的代码,在dispatchTouchEvent(ev: MotionEvent?)
里增加了对触摸事件重新拦截的逻辑:
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
if (ev == null) return super.dispatchTouchEvent(ev)
when (ev.action) {
MotionEvent.ACTION_DOWN -> {
parent.requestDisallowInterceptTouchEvent(true)
}
MotionEvent.ACTION_MOVE -> {
val x = ev.x
val y = ev.y
val disX: Float = x - _lastTouchX
val disY: Float = y - _lastTouchY
//是否出现横向滑动
if (Math.abs(disX) > Math.abs(disY)) {
if (disX > 0) {
//触发左滑,通过确定是否可以左滑来确定是否需要拦截触摸事件
val canScrollLeft = canScrollHorizontally(-1)
parent.requestDisallowInterceptTouchEvent(canScrollLeft)
} else if (disX < 0) {
//触发右滑,通过确定是否可以右滑来确定是否需要拦截触摸事件
val canScrollRight = canScrollHorizontally(1)
parent.requestDisallowInterceptTouchEvent(canScrollRight)
}
} else {
parent.requestDisallowInterceptTouchEvent(false)
}
}
MotionEvent.ACTION_UP -> {
}
}
_lastTouchX = ev.x
_lastTouchY = ev.y
return super.dispatchTouchEvent(ev)
}
关键字:RecyclerView嵌套、竖RecyclerView嵌套横向RecyclerView、横向RecyclerView嵌套横向RecyclerView。