[TOC]
1. 什么是ViewPager?
android.support.v4.view.ViewPager
v4扩展包中的一个类,用于实现view或者fragment在ViewPager上的左右切换.
ViewPager和之前常用LinearLayout一样,都是布局容器,我们可以在里面添加我们想要显示的内容但是每个viewpager都需要适配器,根据子项的不同选择不同的适配器.
2. ViewPager怎么用?
简单的先在xml中拉一个ViewPager控件,然后在活动中find到这个控件. 然后就是准备好要显示的内容比如view或者fragment什么的...添加到List中去 ,再去定义适配器.(和listview的用法差不多)
2.1 常用的基本方法:
setAdapter(PagerAdapter adapter)
设置适配器
setOffscreenPageLimit(int limit)
设置缓存的页面个数,默认是 1
setCurrentItem(int item)
跳转到特定的页面
setOnPageChangeListener(..)
设置页面滑动时的监听器(现在API中建议使用addOnPageChangeListener(..)
) 添加...
setPageTransformer(..PageTransformer)
设置页面切换时的动画效果
setPageMargin(int marginPixels)
设置不同页面之间的间隔
setPageMarginDrawable(..)
设置不同页面间隔之间的装饰图也就是 divide ,要想显示设置的图片,需要同时设置setPageMargin()
2.2 适配器的选择
数据源:List ->PagerAdapter
数据源:List ->FragmentPagerAdapter
数据源:List ->FragmentStatePagerAdapter 可以保存Fragment的状态
PagerAdapter 是抽象的类,所有实现它的子类必须要实现以下四个方法.
- getCount(); 获取当前窗口的数目
- isViewFromObject(View view,Object object); 判断当前的view是否由对象生产,官方建议直接返回view==object
- instantiateItem(View container,int position); 当页面需要缓存或者显示的时候,会调用这个方法用于初始化布局
- destroyItem(ViewGroup container,int position,Object object); 不需要这个页面的时候(不显示也不需要缓存)的时候,会调用这个方法,销毁这个view
**FragmentPagetAdapter:**适用于具有少量的Fragment并且需要经常显示的情况,但是如果有大量的Fragment的时候请使用下面的适配器,因为通常用户访问每个页面的Fragment都保存在内存中,当页面不可见的时候这个Fragment可能会被摧毁但是会占用大量的内存.这是因为对于不再需要的Fragment仅销毁它的视图,并不会销毁Fragment的实例
**FragmentStatePagerAdapter:**适用于当有大量的Fragment需要显示的时候, 当页面对用户不可见的时候,这个Fragment可能会被彻底的销毁,但是这使得pager保存的页面占用更少的内存. state 状态,销毁时,会将其 onSaveInstanceState(Bundle outState)
中的 bundle 信息保存下来,当用户切换回来,可以通过该 bundle 恢复生成新的 fragment,也就是说,你可以在 onSaveInstanceState(Bundle outState)
方法中保存一些数据,在 onCreate 中进行恢复创建.
**总结下来:**只有少量的页面的时候可以使用第一种适配器.加载的时候比较快,但是如果有大量的页面的时候建议使用第二个,不过页面的切换时会产生更大的开销. (销毁以后新建)
复制代码
2.3 需要显示的内容为Fragment
private ViewPager mViewPager;
private List<Fragment> mFragmentList;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView2();
}
private void initView2() {
mViewPager = findViewById(R.id.pager);
mFragmentList = new ArrayList<>();
mFragmentList.add(new MyFragment());
mFragmentList.add(new MyFragment());
mFragmentList.add(new MyFragment());
mFragmentList.add(new MyFragment());
mFragmentList.add(new MyFragment());
mFragmentList.add(new MyFragment());
MyFragmentAdapter myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(), mFragmentList);
mViewPager.setAdapter(myFragmentAdapter);
}
复制代码
适配器中需要重写两个方法
public class MyFragmentAdapter extends FragmentPagerAdapter {
private List<Fragment> mFragmentList;
public MyFragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
super(fm);
mFragmentList = fragmentList;
//fragment的添加和替换都是通过manager来管理的.
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
//用于展示的fragment
}
@Override
public int getCount() {
return mFragmentList.size();
//展示页面的个数
}
}
复制代码
2.4 需要显示的内容为View
private ViewPager mViewPager;
private List<View> mViews;
private PagerAdapter mPagerAdapter;
protected void onCreate(Bundle savedInstanceState) {
...
initView();
}
private void initView() {
mViewPager = findViewById(R.id.pager);
mViews = new ArrayList<>();
mTabLayout = findViewById(R.id.tablayout);
mTabLayout.setupWithViewPager(mViewPager);
LayoutInflater layoutInflater = LayoutInflater.from(MainActivity.this);
View view1 = layoutInflater.inflate(R.layout.item, null);
mViews.add(view1);
View view2 = layoutInflater.inflate(R.layout.item, null);
mViews.add(view2);
View view3 = layoutInflater.inflate(R.layout.item, null);
mViews.add(view3);
View view4 = layoutInflater.inflate(R.layout.item, null);
mViews.add(view4);
View view5 = layoutInflater.inflate(R.layout.item, null);
mViews.add(view5);
mPagerAdapter = new MyPagerAdapter(mViews);
}
复制代码
public class MyPagerAdapter extends PagerAdapter {
private List<View> mViews;
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return arr[position];
}
public MyPagerAdapter(List<View> views) {
mViews = views;
}
//必须重写下面四个方法
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
//super.destroyItem(container, position, object);
//删除页卡
container.removeView(mViews.get(position));
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
//实例化页卡
container.addView(mViews.get(position));
return mViews.get(position);
}
@Override
public int getCount() {
//页卡个数
return mViews.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
}
复制代码
注意适配器中续要重写这四个方法即可
2.5 配合TabLayout使用
首先要在build.gradle中添加依赖: implementation 'com.android.support:design:27.1.1'
通过上面的两个例子显示不同的控件需要使用不同的适配器.
不过搭配TabLayout可以让人知道当前页面显示的是什么东西,并且想要跳跃到相对应的功能的时候也就更加的便捷与方便. 用法和一般的控件差不多,先在资源文件中添加这个控件声明id,然后通过活动findviewbyid()找到这个控件. 接下里在活动中绑定(viewpager等可以参考上面的代码)
...
//在viewpager和适配等初始化以及适配完毕了以后,调用下面的方法将Tablayout与ViewPager绑定起来.
mTabLayout.setupWithViewPager(mViewPager);
...
//下面是在适配器中
//接下来还需要在适配器中重写一个方法,否则标签栏不会显示信息
public CharSequence getPageTitle(int position) {
return arr[position];
//通过任意办法,把要显示的信息传进来, 他会根据页面的位置选择string,所以最好将信息的顺序与页面的顺序匹配起来
}
复制代码
3. 总结
通过上面的那些内容就可以简单的使用ViewPager并与TabLayout联合起来使用,不过ViewPager能做的不仅仅只是这一些,更多的可以看这篇文章:https://juejin.im/post/5a4c2f496fb9a044fd122631#heading-3