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

 

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