Android-ViewPager(翻页控件)

ViewPager(翻页控件)

ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view

1.ViewPager类直接继承了ViewGroup类,所有它是一个容器类,可以在其中添加其他的view类。

2.ViewPager类需要一个PagerAdapter适配器类给它提供数据。

3.ViewPager经常和Fragment一起使用,并且提供了专门的FragmentPagerAdapter和FragmentStatePagerAdapter类供Fragment中的ViewPager使用。

ViewPager经常用来连接Fragment,它很方便管理每个页面的生命周期,使用ViewPager管理Fragment是标准的适配器实现。最常用的实现一般有FragmentPagerAdapter和FragmentStatePagerAdapte

实现一个最基本的PagerAdapter,《必须实现四个方法》,在代码里有注释
public class AdapterViewpager extends PagerAdapter {
private List mViewList;

public AdapterViewpager(List 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 mFragments;

public AdapterFragment(FragmentManager fm, List 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

@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
}

FragmentPagerAdapter适用于页面比较少的情况,FragmentStatePagerAdapter适用于页面比较多的情况

ViewPager的翻页动画

public class DepthPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f;

public void transformPage(View view, float position) {
Log.d(“DepthPageTransformer”, view.getTag() + " , " + position + “”);
int pageWidth = view.getWidth();

  if (position < -1) { // [-Infinity,-1)
      // This page is way off-screen to the left.
      view.setAlpha(0);

  } else if (position <= 0) { // [-1,0]
      // Use the default slide transition when moving to the left page
      view.setAlpha(1);
      view.setTranslationX(0);
      view.setScaleX(1);
      view.setScaleY(1);

  } else if (position <= 1) { // (0,1]
      // Fade the page out.
      view.setAlpha(1 - position);

      // Counteract the default slide transition
      view.setTranslationX(pageWidth * -position);

      // Scale the page down (between MIN_SCALE and 1)
      float scaleFactor = MIN_SCALE
              + (1 - MIN_SCALE) * (1 - Math.abs(position));
      view.setScaleX(scaleFactor);
      view.setScaleY(scaleFactor);

  } else { // (1,+Infinity]
      // This page is way off-screen to the right.
      view.setAlpha(0);
  }

}
}

public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.85f;
private static final float MIN_ALPHA = 0.5f;

@SuppressLint(“NewApi”)
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();

  Log.e("TAG", view + " , " + position + "");

  if (position < -1) { // [-Infinity,-1)
      // This page is way off-screen to the left.
      view.setAlpha(0);

  } else if (position <= 1) 
  { // [-1,1]
      // Modify the default slide transition to shrink the page as well
      float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
      float vertMargin = pageHeight * (1 - scaleFactor) / 2;
      float horzMargin = pageWidth * (1 - scaleFactor) / 2;
      if (position < 0) {
          view.setTranslationX(horzMargin - vertMargin / 2);
      } else {
          view.setTranslationX(-horzMargin + vertMargin / 2);
      }

      // Scale the page down (between MIN_SCALE and 1)
      view.setScaleX(scaleFactor);
      view.setScaleY(scaleFactor);

      // Fade the page relative to its size.
      view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE)
              / (1 - MIN_SCALE) * (1 - MIN_ALPHA));

  } else { // (1,+Infinity]
      // This page is way off-screen to the right.
      view.setAlpha(0);
  }

}
}

简化ViewPager的使用

PagerAdapter简化
public class QuickPageAdapter extends PagerAdapter {
private List mList;

public QuickPageAdapter(List mList) {
this.mList = mList;
}

@Override
public int getCount() {
return mList.size();
}

@Override
public boolean isViewFromObject(View view, Object object) {
return object == view;
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(mList.get(position));
return mList.get(position);
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mList.get(position));
}
}
使用它,这样不用每次都写个适配器
List views = new ArrayList<>();

mViewPager.setAdapter(new QuickPageAdapter(views));

  • FragmentPagerAdapter简化
public class QuickFragmentPageAdapter<T extends Fragment> extends FragmentPagerAdapter {
  private List<T> mList;
  private String[] mStrings;

  /**
   * @param fm
   * @param list
   * @param titles PageTitles
   */
  public QuickFragmentPageAdapter(FragmentManager fm, List<T> list, String[] titles) {
      super(fm);
      mList = list;
      mStrings = titles;
  }

  @Override
  public Fragment getItem(int position) {
      return mList.get(position);
  }

  @Override
  public int getCount() {
      return mList.size();
  }

  @Override
  public CharSequence getPageTitle(int position) {
      return mStrings == null ? super.getPageTitle(position) : mStrings[position];
  }
}

ViewPager结合第三方库实现小圆点指示器效果

public void setViewPager(ViewPager viewPager) {
      mViewpager = viewPager;
      if (mViewpager != null && mViewpager.getAdapter() != null) {
          mLastPosition = -1;
          createIndicators();
          mViewpager.removeOnPageChangeListener(mInternalPageChangeListener);
          mViewpager.addOnPageChangeListener(mInternalPageChangeListener);//绑定上内部实现的PageChangeListener
          mInternalPageChangeListener.onPageSelected(mViewpager.getCurrentItem());
      }
  }

  private final OnPageChangeListener mInternalPageChangeListener = new OnPageChangeListener() {

      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
      }

      @Override public void onPageSelected(int position) {//这里是动画的核心

          if (mViewpager.getAdapter() == null || mViewpager.getAdapter().getCount() <= 0) {
              return;
          }

          if (mAnimatorIn.isRunning()) {
              mAnimatorIn.end();
              mAnimatorIn.cancel();
          }

          if (mAnimatorOut.isRunning()) {
              mAnimatorOut.end();
              mAnimatorOut.cancel();
          }

          View currentIndicator;
          if (mLastPosition >= 0 && (currentIndicator = getChildAt(mLastPosition)) != null) {//页面离开屏幕时指示器动画
              currentIndicator.setBackgroundResource(mIndicatorUnselectedBackgroundResId);
              mAnimatorIn.setTarget(currentIndicator);
              mAnimatorIn.start();
          }

          View selectedIndicator = getChildAt(position);
          if (selectedIndicator != null) {//页面进入屏幕时指示器动画
              selectedIndicator.setBackgroundResource(mIndicatorBackgroundResId);
              mAnimatorOut.setTarget(selectedIndicator);
              mAnimatorOut.start();
          }
          mLastPosition = position;
      }

      @Override public void onPageScrollStateChanged(int state) {
      }
  };


你可能感兴趣的:(Android)