Android开发:这可能是ViewPager2滑动冲突最全的处理方案,内外兼修,解决冲突!

本文详细探讨了ViewPager2在Android开发中出现的滑动冲突问题及其解决方案。作者指出,相较于ViewPager,ViewPager2未处理滑动冲突,需要开发者自行解决。文章介绍了外部拦截法和内部拦截法,并提供了具体的代码示例,特别是内部拦截法在ViewPager2Container中的应用,以解决嵌套滑动冲突。此外,还强调了成为一名优秀程序员需要不断学习和积累的重要性。
摘要由CSDN通过智能技术生成

背景

自去年12月份ViewPager2正式版发布以后,ViewPager2已经逐渐开始替代旧版本的ViewPager。许多开发者也已经在项目中使用了ViewPager2。相比ViewPager,ViewPager2的功能不可谓不强大。

我在之前写过的一篇文章

学不动也要学!深入了解ViewPager2

https://zhpanvip.gitee.io/2019/12/14/24.Know%20about%20ViewPager2/

对ViewPager2的使用做过详细的讲解。但是,由于当时没有太多实战,所以并没有发现ViewPager2的嵌套使用存在严重的滑动冲突。

直到今年三月份用ViewPager2重构BannerViewPager的时候才发现这个问题。因此,在BVP 3.0版本中额外对ViewPager2做了滑动冲突处理,效果还算差强人意。另外,曾在论坛上看到过不少ViewPager2滑动冲突的求助帖子,甚至还有同学因为搜索ViewPager2滑动冲突而找到了BannerViewPager的Github主页。既然如此,不如写篇文章将BVP处理滑动冲突的经验分享给大家,没准还能涨知 (fěn) 识 (sī),嘿嘿嘿。

为什么ViewPager没有冲突

不知道你是否有这个疑问,在ViewPager时代,ViewPager嵌套ViewPager并没有出现过滑动冲突。可是为什么在ViewPager的升级版ViewPager2中却出现了滑动冲突呢?想要搞清楚这个问题就需要我们深入到ViewPager和ViewPager2的内部分析一下它们的源码了。

我们知道,滑动冲突是需要在onInterceptTouchEvent方法中进行处理的,根据自身条件来决定是否要拦截事件。在ViewPager的源码中看到以下代码(方便阅读,代码做了删减):

@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        final int action = ev.getAction() & MotionEvent.ACTION_MASK;
        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
            // 在事件取消或者抬起手指后重置状态
            resetTouch();
            return false;
        }

        switch (action) {
            case MotionEvent.ACTION_MOVE: {
                // 这里判断在水平方向上的滑动距离大于竖直方向的2倍,则认为是有效的切换页面的滑动
                if (xDiff > mTouchSlop && xDiff * 0.5f > yDiff) { 
                    mIsBeingDragged = true;
                    // 禁止Parent View拦截事件,即事件要能够传递到ViewPager
                    requestParentDisallowInterceptTouchEvent(true);
                    setScrollState(SCROLL_STATE_DRAGGING);
                } else if (yDiff > mTouchSlop) {
                    mIsUnableToDrag = true;
                }
                break;
            }

            case MotionEvent.ACTION_DOWN: {     
                if (mScrollState == SCROLL_STATE_SETTLING
                        && Math.abs(mScroller.getFinalX() - mScroller.getCurrX()) > mCloseEnough) {
                       // 在Down事件中禁止Parent View拦截事件,是为了事件序列能够传递到ViewPager
                    requestParentDisallowInterceptTouchEvent(true);
                    setScrollState(SCROLL_STATE_DRAGGING);
                } else {
                    completeScroll(false);
                    mIsBeingDragged = false;
                }
                break;
            }

            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;
        }
        return mIsBeingDragged;
    } 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值