ViewPager 重新可見(jiàn)時(shí)bug
-
項(xiàng)目場(chǎng)景
最近項(xiàng)目正在做自動(dòng)輪播的banner效果俯画,出現(xiàn)了幾種意想不到的問(wèn)題。
1:由于banner是放在recyclerview 中的head中懂从,所有當(dāng)滑動(dòng)recyclerview 至banner到屏幕外再回來(lái),
會(huì)發(fā)現(xiàn)蹲蒲,viewpager第一次切換pager 無(wú)動(dòng)畫(huà)效果番甩,也就是翻頁(yè)速度很快。
2:當(dāng)從別的fragment頁(yè)面中切換到有banner的fragment中的時(shí)候届搁,也就是banner中的fragment由
isVisibleToUser=false 變成 isVisibleToUser=true時(shí) 會(huì)出現(xiàn)viewpager中兩個(gè)pager卡著不動(dòng)缘薛,過(guò)段時(shí)間才會(huì)恢復(fù)并且切換無(wú)動(dòng)畫(huà)
-
bug背景
當(dāng)ViewPager不可見(jiàn)時(shí),會(huì)執(zhí)行其onDetachedFromWindow方法卡睦,再次可見(jiàn)時(shí)會(huì)執(zhí)行onAttachedToWindow方法,這時(shí)候會(huì)出現(xiàn)以下bug:
-
1.在Android4.0上會(huì)出現(xiàn)第一次自動(dòng)滑動(dòng)沒(méi)有動(dòng)畫(huà)效果宴胧。
-
2.在Android5.0上會(huì)出現(xiàn)第一次滑動(dòng)不僅沒(méi)有動(dòng)畫(huà)效果,而且連View都沒(méi)有表锻。
-
3.當(dāng)ViewPager自動(dòng)滑動(dòng)到一半的時(shí)候恕齐,將其隱藏后,無(wú)法自動(dòng)滑完瞬逊。會(huì)出現(xiàn)滑一半的情況显歧。
-
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!!!! 細(xì)看
viewpager 源碼中有個(gè)mFirstLayout 成員變量,當(dāng)mFirstLayout=true時(shí)确镊,是不走scrollToItem方法的追迟,
所以會(huì)導(dǎo)致頁(yè)面重新可見(jiàn)時(shí),第一次切換是沒(méi)有動(dòng)畫(huà)的I取6丶洹!J@椤!F跄4铩!P竿颉K┣濉!会通!
-
解決辦法
繼承viewpager 重寫(xiě) onAttachedToWindow()方法口予,反射mFirstLayout 成員變量 修改值
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
/**
* 設(shè)ViewPager中有3張照片
* 直到完全隱藏此ViewPager,并執(zhí)行了onDetachedFromWindow
* 再回來(lái)時(shí)涕侈,將會(huì)出現(xiàn)bug沪停,第一次滑動(dòng)時(shí)沒(méi)有動(dòng)畫(huà)效果,并且,經(jīng)常出現(xiàn)view沒(méi)有加載的情況
*/
try {
Field mFirstLayout = ViewPager.class.getDeclaredField("mFirstLayout");
mFirstLayout.setAccessible(true);
mFirstLayout.set(this, false);
setCurrentItem(getCurrentItem());
} catch (Exception e) {
e.printStackTrace();
}
}