Android UI学习笔记 之 使用ViewPager实现导航
ViewPager的用处就如上图所示(图源网络),当我们左右滑动屏幕时,会从一个页卡转到下一个页卡。
ViewPager中默认三个为一组的加载,例如,view1 view2 view3,当我们向左滑动时,view1会被销毁,
而view4(如果有的话)就会实例化加载进来,变成view2 view3 view4的样子。
使用ViewPager大致分为以下步骤:
①建立数据源List
②将数据源绑定到适配器,不同的数据源有不同的适配器。
③再将适配器绑定到当前的ViewPager中,完成。
当填充的内容不同时,使用的适配器也不同。
PagerAdapter适配器对应的数据源是List
FragmentPagerAdapter适配器对应的数据源是List
FragmentStatePagerAdapter适配器对应的数据源是List
①建立数据源List
ViewPager中可以填充View和Fragment作为页卡。
我们这里以View为例,先新建一个简单的layout,里面只有一个TextView,用来显示第几个页卡。
然后在Activity中将这个layout转换为View对象,有两种方法,这里大致提一下。
//第一种方法 LayoutInflater lf = getLayoutInflater().from(this);//先获取LayoutInflater 对象 lf.inflate(resource, root);//再inflate获取view,resource表示layout的布局文件,root表示需要附加到resource资源文件的根控件 //第二种方法 View.inflate(context, resource, root);//context表示当前的上下文,resouce和root参照上面解释 //这里的root就是说要把layout转换得到的view加载到哪一个ViewGroup里面,我们这里不需要.所以设置为null得到的view在添加到List集合里面,这样第一步建立数据源就完成了。
viewList = new ArrayList(); for (int i = 0; i < 4; i++) { View view = View.inflate(MainActivity.this, R.layout.view, null); ((TextView) view.findViewById(R.id.pageText)).setText("这是第" + i + "个View"); viewList.add(view); }
②将数据源绑定到适配器,不同的数据源有不同的适配器。
我们需要自己来写一个适配器,因为之前用的是View来填充的,所以这里使用PagerAdapter。
public class MyViewPagerAdapter extends PagerAdapter { ListviewList;//页卡的View集合 List titleList;//页卡的标题集合 public MyViewPagerAdapter(List viewList, List titleList) {//自定义的构造方法 this.viewList = viewList; this.titleList = titleList; } @Override public int getCount() { return viewList.size();//返回页卡数量 } @Override public boolean isViewFromObject(View view, Object object) { return view==object;//这个view是否来自object的类型 } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(viewList.get(position));//实例化一个页卡,左右滑动时调用 return viewList.get(position); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(viewList.get(position));//销毁一个页卡,左右滑动时调用 } @Override public CharSequence getPageTitle(int position) { return titleList.get(position);//设置页卡的标题,如上图中的FragmentA,FragmentB,FragmentC } }
里面有一些常用的方法要重写。
getCount()返回的是页卡的数量,也就是你填充进去的View的数量,我们用集合的size()方法返回一个int。isViewFromObject()判断的是view的类型,有时候我们要判断这个view是否为TextView或者Button之类的。instantiateItem()这个方法的用法,就是当页面是view1 view2 view3时,向左滑动,出现view4的时候调用的,用来加载view4,形成view2 view3 view4。destroyItem()和上一个方法同时调用,销毁view1,本质上就是从ViewGroup中删掉view1,加入view4。getPageTitle()显示的是标题,如最上面图中的fragmengA,fragmengB,fragmengC。我们写了个适配器之后,之后当然就是加载数据源了。
第二步的主要工作就是写适配器了。
myViewPagerAdapter = new MyViewPagerAdapter(viewList, titleList);//将List传入,适配器中要写构造方法
③再将适配器绑定到当前的ViewPager中,完成。
先在Activity的XML布局文件中,加入ViewPager。
实现上图中的FragmentA,FragmentB,FragmentC的标题其实有两种方法,
使用PagerTabStrip或者PagerTitleStrip两种,注意只能取其中一种方法。
然后通过layout_gravity来布置,我们把tab放在顶部,title放在底部。
<android.support.v4.view.viewpager android:id="@+id/viewPager" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"> <android.support.v4.view.pagertabstrip android:id="@+id/tab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" android:background="@color/yellow"> </android.support.v4.view.pagertabstrip> <android.support.v4.view.pagertitlestrip android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="@color/blue"> </android.support.v4.view.pagertitlestrip> </android.support.v4.view.viewpager>会造成tab的失效(PagerTabStrip是PagerTitleStrip的子类,有兴趣的可以看下API)
然后绑定适配器,完成。
viewPager = (ViewPager) findViewById(R.id.viewPager); viewPager.setAdapter(myViewPagerAdapter);
附加:
④如果觉得样式很丑的话,我们可以自定义样式
建议还是实际写一下代码,增加印象。//在pagerTabStrip中有以下方法 pagerTabStrip.setBackgroundColor(int color);//导航栏的背景色 pagerTabStrip.setTextColor(int color);//导航栏的文字色 pagerTabStrip.setDrawFullUnderline(boolean drawFull);//导航栏底线是否显示 pagerTabStrip.setTabIndicatorColor(int color);//当前页卡的选中的线的颜色
⑤如果不是用View,而是用Fragment填充呢
通过查阅API,我们可以知道FragmentPagerAdapter和FragmentStatePagerAdapter是兄弟关系,都是直接继承自PagerAdapter。
两者的区别在于FragmentPagerAdapter不能动态加载页卡,是一次性导入所有页卡,而FragmentStatePagerAdapter是和PagerAdapter一样动态加载页卡的。
和View一样,我们为FragmentPagerAdapter适配器添加数据源List
注意FragmentPagerAdapter是一次性加载所有页卡,所以不用重写instantiateItem()和destroyItem()(这两个方法在FragmentStatePagerAdapter要重写)。
值得注意的是我们需要import android.support.v4.app.Fragment;而不是import android.app.Fragment。
并且,我们的Activity要继承自FragmentActivity,
并且在new对象的时候,要在Activity中用getSupportFragmentManager()获取FragmentManager对象。
public MyFragmentPagerAdapter(FragmentManager fm,ListfragmentList, List titleList) { super(f