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

tech2025-12-10  2

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(); /** * 设ViewPager中有3张照片 * 直到完全隐藏此ViewPager,并执行了onDetachedFromWindow * 再回来时,将会出现bug,第一次滑动时没有动画效果,并且,经常出现view没有加载的情况 */ try { Field mFirstLayout = ViewPager.class.getDeclaredField("mFirstLayout"); mFirstLayout.setAccessible(true); mFirstLayout.set(this, false); setCurrentItem(getCurrentItem()); } catch (Exception e) { e.printStackTrace(); } }
修复:当ViewPager自动滑动到一半的时候,将其隐藏后,无法自动滑完。会出现滑一半的情况。
@Override protected void onDetachedFromWindow() { if (((Activity) getContext()).isFinishing()) { super.onDetachedFromWindow(); } }

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

最新回复(0)