解决viewpager 重新可见时,切换page无动画

   日期:2020-09-05     浏览:95    评论:0    
核心提示:ViewPager 重新可见时bug项目场景最近项目正在做自动轮播的banner效果,出现了几种意想不到的问题。1:由于banner是放在recyclerview 中的head中,所有当滑动recyclerview 至banner到屏幕外再回来,会发现,viewpager第一次切换pager 无动画效果,也就是翻页速度很快。2:当从别的fragment页面中切换到有banner的fragment中的时候,也就是banner中的fragment由isVisibleToUser=false

ViewPager 重新可见时bug

  • 项目场景

最近项目正在做自动轮播的banner效果,出现了几种意想不到的问题。
1:由于banner是放在recyclerview 中的head中,所有当滑动recyclerview 至banner到屏幕外再回来,
会发现,viewpager第一次切换pager 无动画效果,也就是翻页速度很快。
2:当从别的fragment页面中切换到有banner的fragment中的时候,也就是banner中的fragment由
isVisibleToUser=false 变成 isVisibleToUser=true时 会出现viewpager中两个pager卡着不动,过段时间才会恢复并且切换无动画

  • bug背景

当ViewPager不可见时,会执行其onDetachedFromWindow方法,再次可见时会执行onAttachedToWindow方法,这时候会出现以下bug:
  • 1.在Android4.0上会出现第一次自动滑动没有动画效果。
  • 2.在Android5.0上会出现第一次滑动不仅没有动画效果,而且连View都没有。
  • 3.当ViewPager自动滑动到一半的时候,将其隐藏后,无法自动滑完。会出现滑一半的情况。
  • bug原因

   @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mFirstLayout = true;
    }

   void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {
           .....\\省略部分代码

        if (mFirstLayout) {
            // We don't have any idea how big we are yet and shouldn't have any pages either.
            // Just set things up and let the pending layout handle things.
            mCurItem = item;
            if (dispatchSelected) {
                dispatchOnPageSelected(item);
            }
            requestLayout();
        } else {
            populate(item);
            scrollToItem(item, smoothScroll, velocity, dispatchSelected);
        }
    }

WTF!!! 细看
viewpager 源码中有个mFirstLayout 成员变量,当mFirstLayout=true时,是不走scrollToItem方法的,
所以会导致页面重新可见时,第一次切换是没有动画的!!!!!!!!!!!!!

  • 解决办法

继承viewpager 重写 onAttachedToWindow()方法,反射mFirstLayout 成员变量 修改值

 @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        
        try {
            Field mFirstLayout = ViewPager.class.getDeclaredField("mFirstLayout");
            mFirstLayout.setAccessible(true);
            mFirstLayout.set(this, false);

            setCurrentItem(getCurrentItem());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

PS:如果能解决您的bug,能否赞一下~

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服