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();
}
}