ViewPager的那些事

LockJo發表於2017-12-21

目錄:

1、禁止點選tag時ViewPager滾動的過渡動畫。
2、解決adapter的notifyDataSetChanged()無效問題。
3、設定ViewPager的預載入頁數。
4、禁止ViewPager手勢左右切換的操作。
5、ViewPager左右滑動的慣性消失的bug。
6、ViewPager與子View進行通訊。


1、禁止點選tag時ViewPager滾動的過渡動畫:

當我們的ViewPager繫結了TabLayout控制元件的時候,通常都有點選一個tab實現切換ViewPager的功能,但是如果在切換時不想要那個切換動畫,該如何做? **解決方案:**其實很簡單,關鍵程式碼就一句:

//第二個引數就是禁止滾動過渡的效果
mViewPager.setCurrentItem(0, false);
複製程式碼

2、解決adapter的notifyDataSetChanged()無效問題:

如果想實現ViewPager的資料更新,在呼叫adapter的notifyDateSetChanged()會發現並沒有效果,其實並非沒有效果,往後滑動兩頁到第三頁會發現,除了ViewPager預設快取的那三頁資料沒有重新整理之外,後面的(第三頁之後)資料都是重新整理了的,這時再返回第一頁會發現第一頁的資料也發生變化了。 **解決方案:**複寫adapter的getItemPosition方法,返回POSITION_NONE即可。

public int getItemPosition(Object object) {    
  return POSITION_NONE;
}
複製程式碼

存在的問題:這不是PagerAdapter中的Bug,通常情況下,呼叫notifyDataSetChanged方法會讓ViewPager通過Adapter的getItemPosition方法查詢一遍所有child view,這種情況下,所有child view位置均為POSITION_NONE,表示所有的child view都不存在,ViewPager會呼叫destroyItem方法銷燬,並且重新生成,加大系統開銷,並在一些複雜情況下導致邏輯問題。特別是對於只是希望更新child view內容的時候,造成了完全不必要的開銷。更有效地方法:更為靠譜的方法是因地制宜,根據自己的需求來實現notifyDataSetChanged的功能,比如,在僅需要對某個View內容進行更新時,在instantiateItem()時,用View.setTag方法加入標誌,在需要更新資訊時,通過findViewWithTag的方法找到對應的View進行更新即可。


3、設定ViewPager的預載入頁數:

ViewPager預設會預載入左右兩頁的內容,如果想預載入更多,只需呼叫ViewPager的setOffscreenPageLimit()即可。

mViewPager.setOffscreenPageLimit(2); // 設定快取view 的個數(實際有3個,快取2個+正在顯示的1個)
複製程式碼

4、禁止ViewPager手勢左右切換的操作:

**解決方案:**自定義View繼承自ViewPager,程式碼如下:

public class ViewPagerEx extends ViewPager{
    private boolean isPagingEnabled = true;

    public ViewPagerEx(Context context) {
        super(context);
    }
    public ViewPagerEx(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onInterceptTouchEvent(event);
    }

    public void setPagingEnabled(boolean canScroll) {
        this.isPagingEnabled = canScroll;
    }

    @Override
    public void setCurrentItem(int item, boolean smoothScroll) {
        super.setCurrentItem(item, smoothScroll);
    }
}
複製程式碼

使用方法:

mViewPager.setPagingEnabled(false);//禁止左右滑動
mViewPager.setPagingEnabled(true);//開啟左右滑動
複製程式碼

5、ViewPager左右滑動的慣性消失的bug。

檢查下FragmentPagerAdapter的構造方法是不是傳了getFragmentManager()?如果是,改為getChildFragmentManager()即可,沒錯,就是這麼簡單。


6、ViewPager與子View進行通訊。

比如我想在ViewPager每滑動結束後,通知子View並進行重新整理。

//利用Tag去獲取到對應的子View,然後對View進行操作。
 viewPager.findViewWithTag(position);
//在Adapter的instantiateItem方法中給子View設定Tag
view.setTag(position);
複製程式碼

(不定期更新)

相關文章