zoukankan      html  css  js  c++  java
  • ViewPager学习及使用(一)

    一:基础篇

      

    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

  • 相关阅读:
    从与计算机结缘说起
    个人作业2:APP案例分析
    团队作业4——第一次项目冲刺(Alpha版本)第二篇
    团队项目作业1团队展示与选题
    团队作业4——第一次项目冲刺(Alpha版本)第三篇
    团队作业3——需求改进&系统设计
    技术博客
    技术博客二
    bootstrap前端框架使用总结分享
    ADO.NET Entities Framework 的增删查改(我自己写的,可以作为范例)
  • 原文地址:https://www.cnblogs.com/ProtectedDream/p/6413098.html
Copyright © 2011-2022 走看看