一:基础篇

  

1.ViewPager的简介和作用
ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view
1)ViewPager类直接继承了ViewGroup类,所有它是一个容器类,可以在其中添加其他的view类。
2)ViewPager类需要一个PagerAdapter适配器类给它提供数据。
3)ViewPager经常和Fragment一起使用,并且提供了专门的FragmentPagerAdapter和FragmentStatePagerAdapter类供Fragment中的ViewPager使用。

2.ViewPager的适配器
简介中提到了PagerAdapter,和ListView等控件使用一样,需要ViewPager设置PagerAdapter来完成页面和数据的绑定,这个PagerAdapter是一个基类适配器,我们经常用它来实现app引导图,它的子类有FragmentPagerAdapter和FragmentStatePagerAdapter,这两个子类适配器用于和Fragment一起使用,在安卓应用中它们就像listview一样出现的频繁。

实现一个最基本的PagerAdapter,《必须实现四个方法》,在代码里有注释

public class AdapterViewpager extends PagerAdapter {
private List<View> mViewList; public AdapterViewpager(List<View> mViewList) {
this.mViewList = mViewList;
} @Override
public int getCount() {//必须实现
return mViewList.size();
} @Override
public boolean isViewFromObject(View view, Object object) {//必须实现
return view == object;
} @Override
public Object instantiateItem(ViewGroup container, int position) {//必须实现,实例化
container.addView(mViewList.get(position));
return mViewList.get(position);
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {//必须实现,销毁
container.removeView(mViewList.get(position));
}
}

实现一个最基本的FragmentPagerAdapter

public class AdapterFragment extends FragmentPagerAdapter {
private List<Fragment> mFragments; public AdapterFragment(FragmentManager fm, List<Fragment> mFragments) {
super(fm);
this.mFragments = mFragments;
} @Override
public Fragment getItem(int position) {//必须实现
return mFragments.get(position);
} @Override
public int getCount() {//必须实现
return mFragments.size();
} @Override
public CharSequence getPageTitle(int position) {//选择性实现
return mFragments.get(position).getClass().getSimpleName();
}
}

FragmentStatePagerAdapter的实现和FragmentPagerAdapter的实现一样就不在写了

3个适配器的基本实现讲完了是不是很简单,那他们的区别是什么呢?
PagerAdapter是基类适配器是一个通用的ViewPager适配器,相比PagerAdapter,FragmentPagerAdapter和FragmentStatePagerAdapter更专注于每一页是Fragment的情况,而这两个子类适配器使用情况也是有区别的。FragmentPagerAdapter适用于页面比较少的情况,FragmentStatePagerAdapter适用于页面比较多的情况。为什么?简单分析下两个适配器的源码就可以知道了。

FragmentStatePagerAdapter

@Override
public Object instantiateItem(ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);//fragment被释放后这里得到的null值
if (f != null) {
return f;
}
} if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
} Fragment fragment = getItem(position);//fragment被释放后或者是初次进入页面拿到新的Fragment实例
if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
if (mSavedState.size() > position) {
Fragment.SavedState fss = mSavedState.get(position);
if (fss != null) {
fragment.setInitialSavedState(fss);
}
}
while (mFragments.size() <= position) {
mFragments.add(null);
}
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
mFragments.set(position, fragment);
mCurTransaction.add(container.getId(), fragment);//新的Fragment实例 是add上去的 return fragment;
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment) object; if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
+ " v=" + ((Fragment)object).getView());
while (mSavedState.size() <= position) {
mSavedState.add(null);
}
mSavedState.set(position, fragment.isAdded()
? mFragmentManager.saveFragmentInstanceState(fragment) : null);
mFragments.set(position, null);//真正释放了fragment实例 mCurTransaction.remove(fragment);
}

FragmentPagerAdapter

@Override
public Object instantiateItem(ViewGroup container, int position) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
} final long itemId = getItemId(position); // Do we already have this fragment?
String name = makeFragmentName(container.getId(), itemId);
Fragment fragment = mFragmentManager.findFragmentByTag(name);
if (fragment != null) {
if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
mCurTransaction.attach(fragment);//因为fragment实例没有被真正释放,所以可以直接attach效率高
} else {
fragment = getItem(position);//初始化页面的时候拿到fragment的实例
if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
mCurTransaction.add(container.getId(), fragment,
makeFragmentName(container.getId(), itemId));//add上去
}
if (fragment != mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
} return fragment;
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
+ " v=" + ((Fragment)object).getView());
mCurTransaction.detach((Fragment)object);//并没有真正释放fragment对象只是detach
}

从源码中我们可以看出FragmentStatePagerAdapter中fragment实例在destroyItem的时候被真正释放,所以FragmentStatePagerAdapter省内存。FragmentPagerAdapter中的fragment实例在destroyItem的时候并没有真正释放fragment对象只是detach,所以FragmentPagerAdapter消耗更多的内存,带来的好处就是效率更高一些。所以得出这样的结论:FragmentPagerAdapter适用于页面比较少的情况,FragmentStatePagerAdapter适用于页面比较多的情况,因此不同的场合选择合适的适配器才是正确的做法

3.ViewPager的翻页动画

为ViewPager设置适配器后,就可以正常使用了,接下来我们为ViewPager增加翻页动画,毕竟人的审美会疲劳,加上一些动画交互会提高不少逼格~~,ViewPager提供了PageTransformer接口用于实现翻页动画。
官方提供了PageTransformer的实现例子。

原文:http://www.jianshu.com/p/e5abbda4a71c

最新文章

  1. JS入门学习,写一个简单的选项卡
  2. Angualar:指令大全
  3. jdk1.6官方下载地址
  4. EOF的一点注记
  5. SharePoint 2010 列表项事件接收器 ItemAdded 的使用方法
  6. 程序猿必备的10款web前端开发插件一
  7. 征服恐惧!用 Vim 写 iOS App
  8. spring-mvc整合jquery cropper图片裁剪插件
  9. 【转】三大UML建模工具Visio、Rational Rose、PowerDesign的区别
  10. HttpClient入门三
  11. Chapter 2 User Authentication, Authorization, and Security(6):服务器权限授予粒度
  12. sequelize 中文文档
  13. 谷歌搜索技巧(转)https://www.runningcheese.com/google
  14. IC卡冷复位时序
  15. DRBD数据镜像与搭建
  16. 深入JVM对象引用
  17. python code(1)
  18. ELK日志收集分析平台 (Elasticsearch+Logstash+Kibana)使用说明
  19. 前端性能优化:配置ETag
  20. 算法笔记_001:斐波那契数的多种解法(Java)

热门文章

  1. HTML5与XML的区别
  2. linux学习笔记18--文件/chmod/chown/chgrp
  3. Unix系统编程()close系统调用
  4. hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)
  5. Ladies&#39; Choice UVALive - 3989 稳定婚姻问题 gale_shapley算法
  6. C++Primer学习笔记《2》
  7. ubuntu 终端$换行
  8. hdu4456 Crowd(二维树状数组)
  9. 【BZOJ2194】快速傅立叶之二
  10. [LintCode] 第k大元素