ViewPager2滑动灵敏-外部法拦截

51 阅读1分钟

1.ViewPager2滑动灵敏问题

ViewPager2嵌套Fragment 左右滑动过于灵敏,网上给出的一个解决方案是增加开始滑动的距离,但是有个明显问题:开始滑动距离增加,导致了触发横滑的难度增加,没有根本性解决问题。

比如横滑一段距离后竖滑,两种滑动状态都能触发,会有一些诡异的现象。为解决这个问题,可以在一次滑动周期内只允许横滑或只允许竖滑。

val recyclerViewField: Field = ViewPager2::class.java.getDeclaredField("mRecyclerView")
recyclerViewField.isAccessible = true
val recyclerView = recyclerViewField.get(viewPager) as RecyclerView
val touchSlopField: Field = RecyclerView::class.java.getDeclaredField("mTouchSlop")
touchSlopField.isAccessible = true
val touchSlop = touchSlopField.get(recyclerView) as Int
touchSlopField.set(recyclerView, touchSlop * 7) //6 is empirical value

为解决ViewPager2滑动灵敏问题,可以在ViewPager2与实际有滑动问题的页面中间增加一个容器,这个容器来处理滑动冲突。

override fun onInterceptTouchEvent(e: MotionEvent): Boolean {

    Log.d(TAG, "onInterceptTouchEvent: ${e.action}")
    when (e.action) {
        MotionEvent.ACTION_DOWN -> {
            startX = e.x
            startY = e.y
            mState = ScrollState.None
            parent.requestDisallowInterceptTouchEvent(true) // 初始禁止父容器拦截
        }
        MotionEvent.ACTION_MOVE -> {
            val dx = abs(e.x - startX)
            val dy = abs(e.y - startY)
            if ((dx > mTouchSlop || dy > mTouchSlop) && mState == ScrollState.None) {
                mState = if (dx > mTouchSlop) ScrollState.Horizontal else ScrollState.Vertical
            }
            if (mState == ScrollState.Horizontal) {
                parent.requestDisallowInterceptTouchEvent(false)
            } else if (mState == ScrollState.Vertical) {
                parent.requestDisallowInterceptTouchEvent(true)
            }
        }

        MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {

        }
    }
    return super.onInterceptTouchEvent(e)

}

enum class ScrollState {
    None,
    Horizontal,
    Vertical
}