ViewPager2滑动事件冲突

1. 场景分析

  1. RecyclerView或SwipeRefreshLayout中嵌套ViewPager2,ViewPager2左右滑动困难,事件容易给RecyclerView或SwipeRefreshLayout吃掉。

  2. ViewPager2中嵌套SwipeRefreshLayout,SwipeRefreshLayout和RecyclerView上下滑动困难。

解决方案分是干预事件分发,判断手势是左右或上下滑动。

2. 代码实现


    <declare-styleable name="FixDragLayout">
        <attr name="android:orientation" />
    declare-styleable>
class FixDragLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    private var downX: Float = 0f
    private var downY: Float = 0f
    private var isDragged = false
    private val touchSlop = ViewConfiguration.get(context).scaledTouchSlop
    val HORIZONTAL = LinearLayout.HORIZONTAL
    val VERTICAL = LinearLayout.VERTICAL
    private var orientation = HORIZONTAL

    init {
        attrs?.let {
            val a = context.obtainStyledAttributes(attrs, R.styleable.FixDragLayout)
            orientation = a.getInt(R.styleable.FixDragLayout_android_orientation, HORIZONTAL)
            a.recycle()
        }
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                downX = ev.x
                downY = ev.y
                isDragged = false
            }
            MotionEvent.ACTION_MOVE -> {
                if (!isDragged) {
                    val dx = abs(ev.x - downX)
                    val dy = abs(ev.y - downY)
                    if (orientation == HORIZONTAL) {
                        isDragged = dx > touchSlop && dx > dy
                    } else if (orientation == VERTICAL) {
                        isDragged = dy > touchSlop && dy > dx
                    }
                }
                parent.requestDisallowInterceptTouchEvent(isDragged)
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                isDragged = false
                parent.requestDisallowInterceptTouchEvent(false)
            }
        }
        return super.onInterceptTouchEvent(ev)
    }
}

3. 使用方式

1. SwipeRefreshLayout嵌套RecyclerView嵌套ViewPager2

<FixDragLayout android:orientation="horizontal">
    <ViewPager2/>
FixDragLayout>

2. ViewPager2嵌套SwipeRefreshLayout和RecyclerView

<FixDragLayout android:orientation="verticle">
    <SwipleRefreshLayout>
        <RecyclerView />
    SwipleRefreshLayout>
FixDragLayout>

你可能感兴趣的:(Android)