美文网首页
ViewPager.PageTransformer

ViewPager.PageTransformer

作者: code希必地 | 来源:发表于2020-07-08 16:43 被阅读0次

PageTransformer是ViewPager内部定义的接口,实现该接口并应用于ViewPager可以控制ViewPager中item view的滑动效果。
接下来我们看一下PageTransformer源码及api介绍,比较简单

    /**
     * A PageTransformer is invoked whenever a visible/attached page is scrolled.
     * This offers an opportunity for the application to apply a custom transformation
     * to the page views using animation properties.
     *
     * <p>As property animation is only supported as of Android 3.0 and forward,
     * setting a PageTransformer on a ViewPager on earlier platform versions will
     * be ignored.</p>
     */
    public interface PageTransformer {
        /**
         * Apply a property transformation to the given page.
         *
         * @param page Apply the transformation to this page
         * @param position Position of page relative to the current front-and-center
         *                 position of the pager. 0 is front and center. 1 is one full
         *                 page position to the right, and -1 is one page position to the left.
         */
        void transformPage(@NonNull View page, float position);
    }

该接口就一个方法,在ViewPager滑动过程中会触发该方法,我们主要看下这个方法中的两个参数:

  • View page:ViewPager中的页面
  • position:该参数并不是指ViewPager中页面的索引,position是page相对于基准参考点的偏移量,滑动过程中可标识page的偏移程度,周期为1,current page的position为0,上一页的position为-1.0,下一页的position为1.0,依此类推。position随ViewaPger滑动趋势发生相应变化:
    向左滑动时,page相对于基准参考点向左偏移,position减小;向右滑动时page相对于基准参考点向右偏移,position变大,其绝对值反应了page与基准参考点间的距离。我们可以根据position的变化,来实现想要的效果。
    下面我们具体看下position的变化吧。
 mViewPager.setAdapter(adapter = new MyViewPagerAdapter());
 mViewPager.setOffscreenPageLimit(4);
 mViewPager.setPageTransformer(false, new ViewPager.PageTransformer() {
            @Override
            public void transformPage(@NonNull View page, float position) {
                Log.e("TAG", "页面" + page.getTag() + "  position:::" + position);
}
//Log 
 页面0  position:::0.0
 页面1  position:::1.0
 页面2  position:::2.0
 页面3  position:::3.0
 页面4  position:::4.0

在初始化时由于我们设置了setOffscreenPageLimit(4)所以除了当前View之后还会初始化屏幕外的4个View。如果此时向左滑动一直滑动到最后一页的log如下:

页面0  position:::0.0~-1.0~-2.0~-3.0
页面1  position:::1.0~0.0~-1.0~-2.0
页面2  position:::2.0~1.0~0.0~-1.0
页面3  position:::3.0~2.0~1.0~0.0

如果向右滑动到第一页,log如下:

页面0  position:::-3.0~-2.0~-1.0~0.0
页面1  position:::-2.0~-1.0~0.0~1.0
页面2  position:::-1.0~0.0~1.0~2.0
页面3  position:::0.0~1.0~2.0~3.0

通过上面的log我们应该大概清楚了它的规律。下面进入实战,先看下动图。


11451103-0100cf0a691d33bd.gif

实现上面的效果主要分为如下几步:

    1. 如何实现子View的重叠排布。
      ViewPager的子View原本是横向排布的,我们可以通过控制子View进行x轴方向的位移实现重叠。
  int pagerWidth = mViewPager.getWidth();
  float horizontalOffsetBase = (pagerWidth - pagerWidth * 
  CENTER_PAGE_SCALE) / 2 / offscreenPageLimit + 45;
  float translationX = (horizontalOffsetBase - page.getWidth()) * position;
  page.setTranslationX(translationX);

很简单就是让子View平移-positionpage.getWidth()的距离,但是这并不能实现重叠效果,还需要在此基础上向右偏移positionhorizontalOffsetBase 距离才行。实现了这一步的同学肯定会发现此时最上层的View并不是第一个View,下面我们就讲下如何让第一个View在最上层。

    1. 如何实现最上层的View为首个子View
      实现方式有3种:
      1.通过 ViewCompat.setTranslationZ(page, (offscreenPageLimit - position) * 5);
      2.通过ViewCompat.setElevation(page, (offscreenPageLimit - position) * 5);
      3.将mViewPager.setPageTransformer(true, new ViewPager.PageTransformer() )中的第一个参数设置为true即可。
      前两种方法的原理一样,都是改变View在z轴上的深度(高度),它们之间的关系是z值=translationZ+elevation,遗憾的是他们只适用于5.0以上。推荐使用第三种方式。
      其他的就很简单的,不再赘述。最后奉上完整代码
 mViewPager.setPageTransformer(true, new ViewPager.PageTransformer() {
            @Override
            public void transformPage(@NonNull View page, float position) {
                int pagerWidth = mViewPager.getWidth();
                float horizontalOffsetBase = (pagerWidth - pagerWidth * CENTER_PAGE_SCALE) / 2 / offscreenPageLimit + 45;

                if (position >= offscreenPageLimit || position <= -1) {
                    page.setVisibility(View.GONE);
                } else {
                    page.setVisibility(View.VISIBLE);
                }

                if (position >= 0) {
                    float translationX = (horizontalOffsetBase - page.getWidth()) * position;
                    page.setTranslationX(translationX);
                }
                if (position > -1 && position < 0) {
                    float rotation = position * 30;
                    page.setRotation(rotation);
                    page.setAlpha((position * position * position + 1));
                }else if (position > offscreenPageLimit - 1) {
                    page.setAlpha((float) (1 - position + Math.floor(position)));
                } else {
                    page.setRotation(0);
                    page.setAlpha(1);
                }
                if (position == 0) {
                    page.setScaleX(CENTER_PAGE_SCALE);
                    page.setScaleY(CENTER_PAGE_SCALE);
                } else {
                    float scaleFactor = Math.min(CENTER_PAGE_SCALE - position * 0.1f, CENTER_PAGE_SCALE);
                    page.setScaleX(scaleFactor);
                    page.setScaleY(scaleFactor);
                }

                ViewCompat.setElevation(page, (offscreenPageLimit - position) * 5);
            }
        });

相关文章

网友评论

      本文标题:ViewPager.PageTransformer

      本文链接:https://www.haomeiwen.com/subject/wqvccktx.html