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

  • 相关阅读:
    golang删除数组某个元素
    golang用通道实现信号量,控制并发个数
    什么是ScaleIO中的forwards rebuild和backwards rebuild?
    SQL Server中的database checkpoint
    如何将thick provision lazy zeroed的VMDK文件转换为thick provision eager zeroed?
    LoadTestAgentResultsLateException in VS2010
    SQL Server Instance无法启动了, 因为TempDB所在的分区没有了, 怎么办?
    VMware vCenter中, 如何辩认虚机上Raw Device Mapping过了的一块物理磁盘?
    SQL Server AlwaysOn Setup Step-By-Step Guide
    TPC-E在populate测试Database时需要注意的一些事项
  • 原文地址:https://www.cnblogs.com/ProtectedDream/p/6413098.html
Copyright © 2011-2022 走看看