ViewPager 剖析及使用

ViewPager的剖析及使用详解


ViewPager在开发中的使用频率非常的高,所以在此做个总结。

主要包括以下几方面:

  • ViewPager的简介和作用
  • ViewPager的适配器
  • ViewPager的翻页动画
  • ViewPager结合第三方库实现小圆点指示器效果
  • 基于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));

    }
}


3个适配器的基本实现很简单,那他们的区别是什么呢?
PagerAdapter是基类适配器是一个通用的ViewPager适配器,相比PagerAdapter,FragmentPagerAdapter和FragmentStatePagerAdapter更专注于每一页是Fragment的情况,而这两个子类适配器使用情况也是有区别的。FragmentPagerAdapter适用于页面比较少的情况,FragmentStatePagerAdapter适用于页面比较多的情况。
FragmentPagerAdapter适用于页面比较少的情况,FragmentStatePagerAdapter适用于页面比较多的情况,因此不同的场合选择合适的适配器才是正确的做法

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

PageTransformer的实现例子

  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);
        }
    }
}

实现翻页动画的关键就是重写transformPage方法,方法里有两个参数view和position,理解这两个参数非常重要。假设有三个页面view1,view2,view3从左至右在viewPager中显示

  • 往左滑动时:view1,view2,view3的position都是不断变小的。
                   view1的position: 0 → -1 → 负无穷大
                   view2的position: 1 → 0 → -1 
                   view3的position: 1 → 0
  • 往右滑动时:view1,view2,view3的position都是不断变大的。
                   view1的position: -1 → 0 
                   view2的position: -1 → 0 → 1 
                   view3的position: 0 → 1→ 正无穷大
    当position是正负无穷大时view就离开屏幕视野了。因此最核心的控制逻辑是在[-1,0]和(0,1]这两个区间,通过设置透明度,平移,旋转,缩放等动画组合可以实现各式各样的页面变化效果
4.简化ViewPager的使用

这里只是做了最简单的封装,可以根据需要调整

  • PagerAdapter简化

    public class QuickPageAdapter<T extends View> extends PagerAdapter {
      private List<T> mList;
    
      public QuickPageAdapter(List<T> 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<View> views = new ArrayList<>();
...
mViewPager.setAdapter(new QuickPageAdapter<View>(views));

提高篇

1.ViewPager结合第三方库实现小圆点指示器效果
https://github.com/ongakuer/CircleIndicator

2.基于ViewPager实现广告轮播控件
https://github.com/daimajia/AndroidImageSlider








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值