解决ViewPager与SwipeRefreshLayout滑动冲突

当SwipeRefreshLayout嵌套ViewPager的时候,滑动的时候很不灵敏,而且在左右滑动的往往都会触发SwipeRefreshLayout的刷新操作,所以我们需要自定义ViewPager和SwipeRefreshLayout,采用内部拦截法来解决滑动冲突,内部拦截法是指父容器不拦截任何事件,所有的事件都会传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交给父容器进行处理。
首先需要重写子元素的dispatchTouchEvent方法,在ACTION_DOWN事件的时候,请求SwipeRefreshLayout不要拦截,只有在ACTION_MOVE事件的时候,并且判断是垂直滑动的话,才请求SwipeRefreshLayout拦截。

class MyViewPager : ViewPager {

    private var startX = 0f
    private var startY = 0f
    private var moveX = 0f
    private var moveY = 0f
    private var deltaX = 0f
    private var deltaY = 0f

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                startX = ev.x
                startY = ev.y
                ViewCompat.setNestedScrollingEnabled(this,true)
                parent.requestDisallowInterceptTouchEvent(true)
            }
            MotionEvent.ACTION_MOVE -> {
                moveX = ev.x
                moveY = ev.y
                deltaX = abs(moveX - startX);
                deltaY = abs(moveY - startY);
                if (deltaX < deltaY) {
                    parent.requestDisallowInterceptTouchEvent(false)
                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
            }
        }
        return super.dispatchTouchEvent(ev)
    }
}

其次,父容器不能拦截ACTION_DOWN事件,因为ACTION_DOWN事件并不受FLAG_DISALLOW_INTERCEPT这个标记位的控制,所以一旦父容器拦截了ACTION_DOWN事件,所有的事件都无法传递到子元素中去了,这样内部拦截就无法起作用了。

class MyRefreshLayout : SwipeRefreshLayout {
    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        if (ev.action == MotionEvent.ACTION_DOWN) {
            super.onInterceptTouchEvent(ev)
            return false
        }
        return true
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值