异常缘由:
NestedScrolling
如果有嵌套的情况下可能会导致NestScrollView
滑动已完成但内部OverScroller
并未finish,由此导致mIsBeingDragged
一直为true
,而NestScrollView
是通过mIsBeingDragged
拦截事件的,最后导致事件被NestScrollView
拦截无法传递给子View
,这个问题不知道androidx
有没有解决,但support
包中一直存在
解决方案:
自定义NestScrollView
,重写onTouchEvent
方法,判断触摸事件是取消或抬起时创建一个250秒后执行的线程(这个时间是Scroll
滑动动画算法的默认时间,可以略微修改),然后通过执行smoothScrollBy(0, 0)
或反射强制让OverScroller
调用abortAnimation()
方法
我把解决方案写成了一个类,可以直接
Copy
使用,如果是java开发者可以根据理论自行编写
class CorrectionScrollNestedScrollView : NestedScrollView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
override fun onTouchEvent(ev: MotionEvent?): Boolean {
val result = super.onTouchEvent(ev)
if (ev?.action == MotionEvent.ACTION_CANCEL || ev?.action == MotionEvent.ACTION_UP) {
requestEndScroll()
}
return result
}
/**用于解决ScrollView滑动结束但是scroll仍然没有finish导致的无法点击的问题**/
fun requestEndScroll() {
handler.postDelayed({
try {
val scrollerField = NestedScrollView::class.java.getDeclaredField("mScroller")
scrollerField.isAccessible = true
val scroller = scrollerField.get(this) as OverScroller
scrollerField.isAccessible = false
if (!scroller.isFinished) {
scroller.abortAnimation()
}
} catch (e: Exception) {
e.printStackTrace()
}
}, 240)
}
}