ViewPager控件允许我们构建可以横向滑动的视图,往往配合Fragment一起使用,左右滑动加载不同的fragment实例,进而显示不同的内容。ViewPager使用方法如下:
1. 在Activity布局中使用ViewPager控件
2. 在对应的Activity中获取ViewPager实例,并设置PagerAdapter。
ViewPager在某种程度上和RecyclerView类似,RecyclerView需要借助Adapter提供视图,ViewPager则需要PagerAdapter根据数据源获取每一页展示的fragment实例,其中自然也需要用到FragmentManager实例来对fragment进行管理。
google提供了两个ViewPager的子类来帮助我们简化这一过程,分别是FragmentPagerAdapter和FragmentStatePagerAdapter。这两个类使用方法上基本一致,区别在于卸载不再需要的fragment时,各自采用的处理方法不同:
FragmentStatePagerAdapter:会直接销毁不需要的fragment(名字中state的含义表示可以通过onSavedInstanceState(Bundle)方法来保存fragment中的信息,以便在用户切换回来时,通过该信息恢复原来fragment销毁前的状态)。
FragmentPagerAdapter:对于不再需要的fragment,会调用detach(fragment)而非remove(fragment)。这两种方法的区别在于前者只是让fragment在视图上不可见,但是实例依旧保存在内存中,可以随时恢复变为可见状态。后者则是直接销毁内存实例。所以采用这种PagerAdapter,将把ViewPager中所有显示过的fragment保存在内存中。
在开发过程中,具体使用哪一种要根据实际的使用场景决定,如果ViewPager加载的fragment中需要显示占用较多内存的图片,我们应该使用FragmentStatePagerAdapter。如果ViewPager只是用在只有固定几页的标签页上,我们完全不用担心内存占用过的情况下,可以使用FragmentPagerAdapter。
下面看看如何使用,在对应的显示ViewPager的Activity中:
private ViewPager mViewPager;
private List mDataSource;
@Override
protected void onCreate(Bundle savedInstanceState) {
mViewPager = findViewById(R.id.activity_view_pager);
FragmentManager fragmentManager = getSupportFragmentManager();
mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
@NonNull
@Override
public Fragment getItem(int position) { // 根据数据源返回对应pager的fragment实例
DataBean data = mDataSource.get(position);
return TestFragment.newInstance(data.getId()); // 返回fragment实例
}
@Override
public int getCount() { // 返回数据源的长度,告知pager的总页数
return mCrimes.size();
}
});
}
setAdapter时需要传入一个抽象类FragmentStatePagerAdapter的子类实例,这里采用匿名内部类的方式,而且传入的参数应当调用的是带有两个参数的构造方法,因为仅传入fragmentManager的构造方法已经废弃了,FragmentStatePagerAdapter.java中:
public abstract class FragmentStatePagerAdapter extends PagerAdapter {
......
@Deprecated
public FragmentStatePagerAdapter(@NonNull FragmentManager fm) {
this(fm, BEHAVIOR_SET_USER_VISIBLE_HINT);
}
/**
* Constructor for {@link FragmentStatePagerAdapter}.
*
* If {@link #BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT} is passed in, then only the current
* Fragment is in the {@link Lifecycle.State#RESUMED} state, while all other fragments are
* capped at {@link Lifecycle.State#STARTED}. If {@link #BEHAVIOR_SET_USER_VISIBLE_HINT} is
* passed, all fragments are in the {@link Lifecycle.State#RESUMED} state and there will be
* callbacks to {@link Fragment#setUserVisibleHint(boolean)}.
*
* @param fm fragment manager that will interact with this adapter
* @param behavior determines if only current fragments are in a resumed state
*/
public FragmentStatePagerAdapter(@NonNull FragmentManager fm,
@Behavior int behavior) {
mFragmentManager = fm;
mBehavior = behavior;
}
......
}
以上就是ViewPager的简单用法。如果我们想要指定进入Activity时显示某个特定的pager,可以通过:
mViewPager.setCurrentItem(i);
指定显示pager的索引来完成。
备注:ViewPager包含的fragment布局中是不支持外边距属性的(会失效)。android:layout_margin将不起作用,我们可以改成android:padding的形式。