ViewPager 使用總結及問題討論

viewPager 是一個很常用的控件,應該完全掌握其各種用法,下面記錄一些常規代碼和自己遇到的問題。

viewPager 常規用法

MyAdapter adapter = new MyAdapter(this, mViewList);
mViewPager.setAdapter(adapter);

然後就是adapter 了, adapter 是關鍵,看看adapter

public class MyAdapter extends PagerAdapter {

    private Context mContext;
    private List<View> mViews;

    public MyAdapter(Context context, List<View> viewList){
        mViews = viewList;
        mContext = context;
    }
    
    @Override
    public int getCount() {
        return mViews.size();
    }

    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
        return view == o;
    }
    

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
//        LayoutInflater inflater = LayoutInflater.from(mContext);
//        View view = inflater.inflate(R.layout.page_adapter, container ,false);
//        TextView textView = view.findViewById(R.id.tv);
//        textView.setText(mViews.get(position));

        container.addView(mViews.get(position));
        // return super. instantiateItem(container, position) 這個也不能調用,否則會崩潰
        return mViews.get(position);
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        // super.destroyItem(container, position, object);  這個super 不能調用 否則會崩潰
        container.removeView((View) object);
    }
}

 這裏往adpter裏 添加了一些 view。在activity裏進行添加,

for (int i = 0; i < 5; i++) {
    LinearLayout linearLayout = new LinearLayout(this);
    TextView textView = new TextView(this);
    textView.setText("tv" + i);
    LinearLayout.LayoutParams layoutParams1 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
    layoutParams1.gravity = Gravity.CENTER;
    textView.setGravity(Gravity.CENTER);
    linearLayout.setGravity(Gravity.CENTER);
    textView.setLayoutParams(layoutParams1);
    linearLayout.addView(textView);
    mViewList.add(linearLayout);
}

這樣viewPager 就算是用上了。 後面可以作爲模板代碼,每次要用的話,直接粘貼複製。簡單分析一下:

在adapter中,必須重寫的方法是getCount 和 isViewFromObject ;然後 instantiateItem 和 destroyItem 分別是創建和銷燬 容器中的待裝對象,所以instantiateItem 方法返回的是object 對象,因爲container 事先也不知道要裝什麼。比如,這裏我裝的是view,不過更多的時候裝的是Fragment. 

viewPager 用於Fragment

 針對viewPager和Fragment的配合使用,官方退出了 FragmentPagerAdapter 和 FragmentStatePagerAdapter 這兩款 adapter ,同時,我們應該明白 Fragment 需要進行管理,這裏adapter 也承擔着管理fragment的功能。針對其區別和聯繫,可以參考:

https://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter
https://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter 

主要來說就是一個少量的靜態頁面(變量進行緩存),一個是大量的動態頁面(其他不可見的頁面變量不進行緩存,直接銷燬)。

模板代碼:

public class BaseFragmentAdapter extends FragmentPagerAdapter {
    private BaseFragment[] mFragmentList;

    public BaseFragmentAdapter(FragmentManager fm, BaseFragment[] fragmentList) {
        super(fm);
        this.mFragmentList = fragmentList;
    }


    @Override
    public Fragment getItem(int position) {
        return mFragmentList[position];
    }

    @Override
    public int getCount() {
        if (mFragmentList == null) {
            return 0;
        }
        return mFragmentList.length;
    }

默認需要實現 getItem 和 getCount ,getItem 默認返回Fragment,所以我們必須提供Fragment的數據源,由此instantiateItem 方法可以不進行重寫,因爲instantiateItem方法本來就是創建對象的,而我們已經提供了對象,所以就不必再重寫這個方法了。

 

常見的坑

防止出現白屏 

1. activity 包含多個Fragment (A,B....),然後某個Fragment(A) 又包含多個子Fragment(A1,A2....), 這時候 A 裏面獲取FragmentManager 要用  getChildFragmentManager() ;不能使用getSupportFragmentManager ,否則會出現白屏;

2. 設置預加載數量和禁止緩存

// 防止出現白屏
vpMain.setOffscreenPageLimit(fragment.size);
vpMain.setSaveFromParentEnabled(false);

3. 考慮FragmentStatePageAdapter 替換FragmentPagerAdapter

其他的問題可以參考

1. 總結的很全面 https://guides.codepath.com/android/viewpager-with-fragmentpageradapter
2. FragmentPagerAdapter https://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter
3. https://stackoverflow.com/questions/22485899/fragment-isadded-returns-false-on-an-already-added-fragment  替換benginTrastion
4. https://stackoverflow.com/questions/7746652/fragment-in-viewpager-using-fragmentpageradapter-is-blank-the-second-time-it-is/22677595
5. https://blog.csdn.net/soha_dong/article/details/92659740
6. https://www.cnblogs.com/lianghui66/p/3607091.html
7. https://medium.com/inloopx/adventures-with-fragmentstatepageradapter-4f56a643f8e0

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章