android面試題-okhttp內核剖析
android面試題- Volley源碼剖析
今天做項目用ViewPager.setCurrentItem 方法,如果兩個頁面相聚比較遠,就會閃瞎我的鈦合金雙眼,中間切換大概20個頁面,如下所示:
setCurrentItem第二個參數設置false,四不四很簡單,直接使用如下代碼:
ViewPager.setCurrentItem(position,false);
很不幸的是,使用上面的代碼會出現如下效果,扎心了老鐵:
從第一題點擊切換到第十八題,你會發現頁面顯示空白,如果從第十個頁面切換到第十五個頁面沒事,平時大家估計沒有發現這個bug,一般我們使用ViewPager都是底下5個tab頁面,從第一個切換到第五個沒事,之前我也以為把第二個參數設置false就行,今天才發現,原來如果當頁面比較少的時候,大概十個以內,一般沒有問題,如果超過十個頁面切換就會出現空白,加載不了數據,扎心了,提出解決方案吧,ViewPager滑動使用的是Scroll,咱們把Scroll的滑動時間duration 設置為0就行。
自定義一個Scroll類,用於控制ViewPager滑動速度:public class MScroller extends Scroller {
private static final Interpolator sInterpolator = new Interpolator() { public float getInterpolation(float t) { t -= 1.0f;
return t * t * t * t * t + 1.0f; }};
public boolean noDuration;
public void setNoDuration(boolean noDuration) {
this.noDuration = noDuration;}
public MScroller(Context context) {
this(context,sInterpolator);}
public MScroller(Context context, Interpolator interpolator) {
super(context, interpolator);}
@Overridepublic void startScroll(int startX, int startY, int dx, int dy, int duration) {
if(noDuration)
super.startScroll(startX, startY, dx, dy, 0);
else super.startScroll(startX, startY, dx, dy,duration); }}
1)動態判斷頁面是否需要滑動,如果不需要滑動,設置滑動時間為0;
為方便使用,定義一個輔助類public class ViewPageHelper { ViewPager viewPager; MScroller scroller;
public ViewPageHelper(ViewPager viewPager) {
this.viewPager = viewPager; init(); }
public void setCurrentItem(int item){ setCurrentItem(item,true); }
public MScroller getScroller() {
return scroller; }
public void setCurrentItem(int item, boolean somoth){
int current=viewPager.getCurrentItem();
if(Math.abs(current-item)>1){ scroller.setNoDuration(true); viewPager.setCurrentItem(item,somoth); scroller.setNoDuration(false); }else{ scroller.setNoDuration(false); viewPager.setCurrentItem(item,somoth); } }
private void init(){ scroller=new MScroller(viewPager.getContext()); Class<ViewPager>cl=ViewPager.class;
try { Field field=cl.getDeclaredField("mScroller"); field.setAccessible(true);
field.set(viewPager,scroller); } catch (NoSuchFieldException e) { e.printStackTrace(); }catch (IllegalAccessException e){ e.printStackTrace(); } }}
1)Math.abs(current-item)>1 ,通過數學函數判斷頁面相隔大於1,就設置頁面切換的動畫的時間為0。
2)這樣每次設置頁面的時候,通過 helper 就可以自動選擇是否有時間間隔了。
3)但是這樣有點麻煩,每次還要手動改,而且使用TabLayout或者ViewPagerIndicator的話,它會自動調用ViewPager的方法,無法使用Helper,所以可以採用自定一個ViewPager,代碼如下:
public class SuperViewPager extends ViewPager {
private ViewPageHelper helper;
public SuperViewPager(Context context) {
this(context,null); }
public SuperViewPager(Context context, AttributeSet attrs) {
super(context, attrs); helper=new ViewPageHelper(this); }
@Override public void setCurrentItem(int item) { setCurrentItem(item,true); }
@Override public void setCurrentItem(int item, boolean smoothScroll) { MScroller scroller=helper.getScroller();
if(Math.abs(getCurrentItem()-item)>1){ scroller.setNoDuration(true);
super.setCurrentItem(item, smoothScroll); scroller.setNoDuration(false); }else{ scroller.setNoDuration(false);
super.setCurrentItem(item, smoothScroll); } }}
至此完美解決了,ViewPager.setCurrentItem切換頁面,效果如下: