ViewPager
1、ViewPager
androidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。
常用方法:
setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPageChangeListener(..) 设置页面滑动时的监听器(现在API中建议使用 addOnPageChangeListener(..))setPageTransformer() 设置页面切换时的动画效果setPageMargin() 设置不同页面之间的间隔setPageMarginDrawable() 设置不同页面间隔之间的装饰图也就是 divide ,要想显示设置的图片,需要同时设置 setPageMargin()
ViewPager有3中适配器:PagerAdapter、FragmentPagerAdapter、FragmentStatePager。PagerAdapter是较为通用的一个Adapter。后面两个FragmentPagerAdapter、FragmentStatePager专门用于Fragment。关于Fragment参考另一篇《Fragment》。
2、PagerAdapter
PagerAdapter是基类适配器是一个通用的ViewPager适配器。主要在于继承PagerAdapter,,必须实现2个抽象接口方法:
//页面数量
@Override
public int getCount() {
return 0;
}
//决定一个页面的View对象是否和object关联
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return false;
} 并且重写一下几个方法:
public Object instantiateItem(@NonNull ViewGroup container, int position) {
//
}
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView(mViewList.get(position));
}
public CharSequence getPageTitle(int position) {
//可配合TabLayout标题使用
} 完整示例代码如下,一般通过List<View>集合保存页面。
public class MyViewPagerAdapter extends PagerAdapter {
private Context mContext
private List<View> mViewList;
public MyViewPagerAdapter(Context context, List<View> lists) {
this.mContext = context;
this.mViewList= lists
}
public int getCount() {
return mViewList.size();
}
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
//初始化View
public Object instantiateItem(@NonNull ViewGroup container, int position) {
container.addView(mViewList.get(position));
return mViewList.get(position);
}
//销毁
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView(mViewList.get(position));
}
public CharSequence getPageTitle(int position) {
return "第" + position + "个";
}
}
3、FragmentPagerAdapter
页面较少的时候使用FragmentPagerAdapter,自定义FragmentPagerAdapter,继承FragmentPagerAdapter必须要实现两个接口方法getItem(int position)和getCount()。
@Override
public Fragment getItem(int position) {
return null;
}
@Override
public int getCount() {
return 0;
} 其次,还必须提供构造方法,调用父类的构造方法。推荐使用第二个构造函数:FragmentPagerAdapter(FragmentManager fm,@Behavior int behavior)
@Deprecated
public MyFragmentPageAdapter(@NonNull FragmentManager fm) {
super(fm);
}
//推荐
public MyFragmentPageAdapter(@NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
} 同样的,添加一个List<Fragment>成员变量,保存ViewPager的页面。
public class MyFragmentPageAdapter extends FragmentPagerAdapter {
private List<Fragment> mFragments;
//构造函数
public MyFragmentPageAdapter(@NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
init();
}
//初始化各个页面
private void init() {
mFragments = new ArrayList<>();
mFragments.add(new MyFragment());
...
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
}
4、FragmentStatePagerAdapter
页面较多且复杂的时候使用FragmentStatePagerAdapter
FragmentStatePagerAdapter和前面的FragmentPagerAdapter方法一模一样,实现2个接口方法getItem(int position)和getCount()。
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
} 示例代码:
public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragments;
public MyFragmentStatePagerAdapter(@NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
init();
}
private void init() {
mFragments = new ArrayList<>();
mFragments.add(new MyFragment());
mFragments.add(new BlankFragment());
}
@NonNull
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
}
5、FragmentPagerAdapter和FragmentStatePagerAdapter
二者使用方法基本相同,唯一的区别就在卸载不再需要的fragment时,采用的处理方式不同:
- 使用FragmentStatePagerAdapter会销毁掉不需要的fragment。事务提交后,可将fragment从activity的FragmentManager中彻底移除。类名中的“state”表明:在销毁fragment时,它会将其onSaveInstanceState(Bundle) 方法中的Bundle信息保存下来。用户切换回原来的页面后,保存的实例状态可用于恢复生成新的fragment.
- FragmentPagerAdapter的做法大不相同。对于不再需要的fragment,FragmentPagerAdapter则选择调用事务的detach(Fragment) 方法,而非remove(Fragment)方法来处理它。也就是说,FragmentPagerAdapter只是销毁了fragment的视图,但仍将fragment实例保留在FragmentManager中。因此, FragmentPagerAdapter创建的fragment永远不会被销毁。
6、其它
ViewPager页面之间的切换动画,ViewPager往往还和标题控件PagerTabStrip、TabLayout一起使用,参考《Android标题Tab》。ViewPager自动轮播(Handler+Thread计时实现)的时候需要注意动画的暂停(后台会耗电),越界等问题。
参考博客:
《Android进阶——ViewPager详解之初识ViewPager(一)》
《ViewPager PagerAdapter not updating the View》
ViewPager基本使用
ViewPager 全面剖析及使用详解
《使用 ViewPager 在 Fragment 之间滑动》
《ViewPager FragmentPagerAdapter和FragmentStatePagerAdapter使用》
《FragmentPagerAdapter和FragmentStatePagerAdapter区别》
《如何高效的使用ViewPager,以及FragmentPagerAdapter与FragmentStatePagerAdapter的区别》
《研磨FragmentPagerAdapter的方法》