使用ViewPager实现导航
ViewPager可以使视图左右滑动
ViewPager的声明:<android.support.v4.view.ViewPager> 这么写的原因是为了解决版本兼容性问题。其中android.support.v4是谷歌为了解决版本系统碎片化的问题所提供的兼容的包,主要解决向下兼容的问题,能让高版本的控件在低版本的控件中使用
---------------------------
将Layout布局转换为View对象
(1) LayoutInflater lf = getLayoutInflater().from(this);
(2) View.inflater( context, resource, root )
那么,ViewPager到底是什么东西呢?我们可以把ViewPager视作一个容器,里面可以放置两种东西,一种是View对象,一种是Fragment。
例如,微信顶部导航包括“聊天”、“发现”、“通讯录”,这就相当于放置了3个View,每个View对应着布局文件。ViewPager的数据源便相当于View对象或Fragment对象的集合。
----------------------------
Adapter的配置
1. PagerAdaper 数据源:List<View>
2. FragmentPagerAdapter 数据源:List<Fragment>
3. FragmentStatePagerAdapter 数据源:List<Fragment>
准备数据源 --> 准备适配器 -->加载适配器
适配器分为两类,分别对应View的集合和Fragment集合
view 对象对应的适配器是 PagerAdapter,需要新建一个类去继承PagerAdapter。这一点和之前学的适配器不一样。我们要在MainActivity中用这个类去创建适配器对象。 -------------------------------------------------------------------- 该类需要继承 4 个方法(默认是2个,需要再扩展2个)为的是让ViewPager可以自己去管理自己的数据源,这里也就是View对象。 1. getCount(): 返回页卡的数量; 2. isViewFromObject(View view, Object object): 判断view是否来自对象 3. instantiateItem(ViewGroup container, int position):实例化一个页卡 4. destroyItem(ViewGroup container, int position, Object object):销毁一个页卡 然后需要构建有参的构造方法: private List<View>viewList; //有参构造方法 public MyPagerAdapter(List<View>viewList){ this.viewList=viewList; } ------------------------------------------------------- ViewPager做管理的时候,一般是三个三个地加载,例如当前显示的是view2,它前面是 view1、下一个是 view3,这三个页卡同时加载在一个界面中,而view4还没有加载。继续向右滑动,view4被实例化,显示的是view3,前面是view2,后面是view4,而 view1 则被移除掉了。
ViewPager设置标题 1. 在 main.xml文件中的ViewPager中添加控件<android.support.v4.view.PagerTabStrip>; 2. 在 MainActivity中创建 PagerTabStrip 对象tab; 3. 注意标题也需要存放在List集合里,所以要声明集合 List<String> titleList; 4. 为ViewPager页卡设置标题 实例化标题集合: titleList = new ArrayList<String>(); 添加标题:titleList.add("第一页"); titleList.add("第一页"); 等等。。。 5. 为了将标题集合传给ViewPager,需要改写适配器的构造方法,向构造方法添加参数List<String>; private List<String> titleList; //有参构造方法 public MyPagerAdapter(List<View>viewList,List<String> titleList){ this.viewList=viewList; this.titleList=titleList; } 6. 在适配器类中重写方法 getPageTitle(): @Override public CharSequence getPageTitle(int position) { return titleList.get(position); } 7. 在 MianActivity 加载适配器 MyPagerAdapter adapter = new MyPagerAdapter(viewList,titleList); 8.可以为为ViewPager设置属性,显得更美观(在此之前要初始化tab):tab.setBackgroundColor(Color.RED) ------------------------------- 如果在 main.xml同时写上 <android.support.v4.view.PagerTabStrip> 和 <android.support.v4.view.PagerTitleStrip>,则前者会失效
//--------------------------mainActivity-------------------------------------
1 package com.example.zy_viewpager; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.support.v4.app.Fragment; 7 import android.support.v4.app.FragmentActivity; 8 import android.support.v4.view.PagerTabStrip; 9 import android.support.v4.view.ViewPager; 10 import android.support.v4.view.ViewPager.OnPageChangeListener; 11 import android.app.Activity; 12 import android.graphics.Color; 13 import android.os.Bundle; 14 import android.view.LayoutInflater; 15 import android.view.Menu; 16 import android.view.MenuItem; 17 import android.view.View; 18 import android.view.ViewGroup; 19 import android.widget.Toast; 20 import android.os.Build; 21 //ViewPager实现导航 22 23 24 25 //PagerAdapter 数据源 List<View>-------xml(view1-4) 26 //FragmentPagerAdapter 数据源 List<Fragment>----xml(fragment1-4分别加载view1-4)---继承FragmentActivity 27 //FragmentStatePagerAdapter 数据源 List<Fragment> 28 public class MainActivity extends FragmentActivity implements OnPageChangeListener { 29 private List<View> viewList;//------xml-view- 30 private ViewPager Pager; 31 32 private PagerTabStrip tap; 33 private List<String> titileList;//标题数据 34 // 如果在 main.xml同时写上 <android.support.v4.view.PagerTabStrip> 和 35 // <android.support.v4.view.PagerTitleStrip>,则前者会失效 36 37 private List<Fragment> fragmentlist; 38 39 @Override 40 protected void onCreate(Bundle savedInstanceState) { 41 super.onCreate(savedInstanceState); 42 setContentView(R.layout.main); 43 Pager = (ViewPager) findViewById(R.id.pager); 44 viewList = new ArrayList<View>(); 45 // 第一种:通过view对象去作viewpager的数据源 46 View view1 = View.inflate(this, R.layout.view1, null); 47 View view2 = View.inflate(this, R.layout.view2, null); 48 View view3 = View.inflate(this, R.layout.view3, null); 49 View view4 = View.inflate(this, R.layout.view4, null); 50 viewList.add(view1); 51 viewList.add(view2); 52 viewList.add(view3); 53 viewList.add(view4); 54 55 // 第二种:通过Fragment作为viewPager的数据源 56 fragmentlist = new ArrayList<Fragment>(); 57 fragmentlist.add(new Fragment1()); 58 fragmentlist.add(new Fragment2()); 59 fragmentlist.add(new Fragment3()); 60 fragmentlist.add(new Fragment4()); 61 62 // 为viewPager页卡设置标题 63 titileList = new ArrayList<String>(); 64 titileList.add("第1页"); 65 titileList.add("第2页"); 66 titileList.add("第3页"); 67 titileList.add("第4页"); 68 69 // 为PagerTabStrip设置一些属性 70 tap = (PagerTabStrip) findViewById(R.id.tap); 71 tap.setBackgroundColor(Color.BLUE); 72 tap.setTextColor(Color.RED); 73 tap.setDrawFullUnderline(false); 74 tap.setTabIndicatorColor(Color.GREEN);//小粗线颜色 75 76 // 创建PagerAdapter适配器 77 MyPagerAdapter adapter = new MyPagerAdapter(viewList, titileList); 78 // viewPager加载适配器 79 // Pager.setAdapter(adapter); 80 81 MyFragmentPagerAdapter adapter2 = new MyFragmentPagerAdapter( 82 getSupportFragmentManager(), fragmentlist, titileList); 83 // Pager.setAdapter(adapter2); 84 85 // 如果ViewPager比较少的话,可以使用 FragmentPagerAdapter。另外还有 86 // FragmentStatePagerAdapter,拥有动态销毁的功能。 87 MyFragmentStatePagerAdapter adapter3 = new MyFragmentStatePagerAdapter( 88 getSupportFragmentManager(), fragmentlist, titileList); 89 Pager.setAdapter(adapter3); 90 91 92 Pager.setOnPageChangeListener(this); 93 94 } 95 96 @Override 97 public void onPageScrollStateChanged(int arg0) { 98 // TODO Auto-generated method stub 99 100 } 101 102 @Override 103 public void onPageScrolled(int arg0, float arg1, int arg2) { 104 // TODO Auto-generated method stub 105 106 } 107 108 @Override 109 public void onPageSelected(int arg0) { 110 // TODO Auto-generated method stub 111 Toast.makeText(this, "当前是第"+(arg0+1)+"个页面", 1).show(); 112 } 113 114 }
//-----------------PagerAdapter------------------------------
1 public class MyPagerAdapter extends PagerAdapter { 2 //自己维护页卡的创建和销毁-只加载三个页卡 3 private List<View> viewlist; 4 private List<String> titileList; 5 6 public MyPagerAdapter(List<View> viewlist, List<String> titileList) { 7 // TODO Auto-generated constructor stub 8 this.viewlist = viewlist; 9 this.titileList = titileList; 10 } 11 12 // 返回的是页卡数量 13 @Override 14 public int getCount() { 15 // TODO Auto-generated method stub 16 return viewlist.size(); 17 } 18 19 // 判断view是否来自对象 20 @Override 21 public boolean isViewFromObject(View arg0, Object arg1) { 22 // TODO Auto-generated method stub 23 return arg0 == arg1; 24 } 25 26 // 实例化一个页卡 27 @Override 28 public Object instantiateItem(ViewGroup container, int position) { 29 // TODO Auto-generated method stub 30 container.addView(viewlist.get(position)); 31 return viewlist.get(position); 32 33 } 34 35 // 销毁页卡 36 @Override 37 public void destroyItem(ViewGroup container, int position, Object object) { 38 // TODO Auto-generated method stub 39 container.removeView(viewlist.get(position)); 40 } 41 42 // 设置viewPager页卡的标题 43 @Override 44 public CharSequence getPageTitle(int position) { 45 // TODO Auto-generated method stub 46 return titileList.get(position); 47 } 48 }
适配器FragmentPagerAdaper
1. 创建 Fragment1~Fragment4,都继承 Fragment,重写onCreateView(),分别使用 inflater.inflate(R.layout.viewX,container,false);将布局文件 viewX.xml(X=1~4)转变为View对象。
2. 在 MainActivity创建 List<Fragment> fragList; 作为ViewPager的数据源。
3. 初始化 fragment 并添加 Fragment 对象:
fragList = new ArrayList<Fragment>();
fragList.add(new Fragment1());
fragList.add(new Fragment2());
fragList.add(new Fragment3());
fragList.add(new Fragment4());
注意 add() 里面是直接新建了 Fragment 对象。
4. 创建 FragmentPagerAdapter 适配器:创建一个类 MyFragmentPagerAdapter ,继承FragmentPagerAdapter。
重写构造方法(如图),使之可以传递参数。
5. 创建适配器。在MainActivity中创建适配器 MyFragmentPagerAdapter 的对象 adapter2。MyFragmentPagerAdapter()需要传递3个参数:
第一个参数是 FragmentManager ,我们需要让 MainActivity继承 FragmentActivity,然后第一个参写做 getSupportFragmentManager();
第二个参数:fragList;
第三个参数:titleList;
6. ViewPager加载适配器 pager.setAdapter(adapter2);
FragmentPagerAdapter 不像 PagerAdapter 那样三个三个地加载页面,而是一次性全部加载,所以不需要构建页卡和销毁页卡。所以,如果ViewPager比较少的话,可以使用 FragmentPagerAdapter。另外还有 FragmentStatePagerAdapter,拥有动态销毁的功能。
四个myFragment继承fragment分别加载view,主activity 继承FragmentActivity
public class Fragment1 extends android.support.v4.app.Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub return inflater.inflate(R.layout.view1, container, false); } }
//-----------------fragmentPagerAdapter-----------------
1 //所有页卡一起加载,不会销毁 2 public class MyFragmentPagerAdapter extends FragmentPagerAdapter { 3 private List<Fragment> fragList; 4 private List<String> titleList; 5 6 public MyFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragList, 7 List<String> titleList) { 8 super(fm); 9 // TODO Auto-generated constructor stub 10 this.fragList = fragList; 11 this.titleList = titleList; 12 } 13 14 @Override 15 public Fragment getItem(int arg0) { 16 // TODO Auto-generated method stub 17 return fragList.get(arg0); 18 } 19 20 @Override 21 public CharSequence getPageTitle(int position) { 22 // TODO Auto-generated method stub 23 return titleList.get(position); 24 } 25 26 @Override 27 public int getCount() { 28 // TODO Auto-generated method stub 29 return fragList.size(); 30 } 31 32 }
---------------------------------------------------------
FragmentStatePagerAdapter的使用,观察页面动态销毁的效果。
1. 复制前面写好的MyFragmentpagerAdapter ,命名为 MyFragmentpagerAdapter2;
2. 将继承的父类改为FragmentStatePagerAdapter;
3. 添加两个重写方法:instantiateItem() 和 destroyItem();
4. 在 Fragment4.java中重写onDestroy():
@Override
public void onDestroy() {
super.onDestroy();
Log.i("main", "Fragment4被销毁了");
}
5. 在 MainActivity中创建FragmentStatePagerAdapter适配器:
MyFragmentPagerAdapter2 adapter3 = new MyFragmentPagerAdapter2(getSupportFragmentManager(),fragList,titleList);
6. ViewPager加载适配器
pager.setAdapter(adapter3);
1 //自己维护页卡的创建和销毁-只加载三个页卡 2 public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter { 3 private List<Fragment> fragList; 4 private List<String> titleList; 5 6 public MyFragmentStatePagerAdapter(FragmentManager fm, List<Fragment> fragList, 7 List<String> titleList) { 8 super(fm); 9 // TODO Auto-generated constructor stub 10 this.fragList = fragList; 11 this.titleList = titleList; 12 } 13 14 @Override 15 public Fragment getItem(int arg0) { 16 // TODO Auto-generated method stub 17 return fragList.get(arg0); 18 } 19 20 @Override 21 public CharSequence getPageTitle(int position) { 22 // TODO Auto-generated method stub 23 return titleList.get(position); 24 } 25 26 @Override 27 public int getCount() { 28 // TODO Auto-generated method stub 29 return fragList.size(); 30 } 31 32 @Override 33 public Object instantiateItem(ViewGroup arg0, int arg1) { 34 // TODO Auto-generated method stub 35 return super.instantiateItem(arg0, arg1); 36 } 37 38 @Override 39 public void destroyItem(ViewGroup container, int position, Object object) { 40 // TODO Auto-generated method stub 41 super.destroyItem(container, position, object); 42 } 43 }
监听器的使用
1. mainActivity实现接口 OnPageChangeListener,并重写3个方法。
2. 3个方法相对重要的是 onPageSelected(int position),这里只重写它,主要是返回当前页面的位置:
@Override
public void onPageSelected(int position) {
Toast.makeText(this, "当前是第"+(position+1)+"个页面 ", Toast.LENGTH_SHORT).show();//注意:position是从0开始计算的。
}
3. ViewPager加载监听器
pager.setOnPageChangeListener(this);
实际工作中,经常使用ViewPager+Fragment的形式,因为Fragment的生命周期是比较全面的。而不使用ViewPager+View,因为View的创建和销毁的逻辑过程没有像Fragment那么好控制。
如果只是图方便,只是做展示,没有太多事务处理的话,可以使用View。
如果业务逻辑比较复杂,推荐使用 ViewPager+Fragment 组合。