千变万化的ViewPager切换动画(二、自定义切换动画)

现在,来尝试自定义一个简单的切换动画。不过,该从何处下手呢?当然是依葫芦画咯~上一片博客不是有提到谷歌官方提供的DepthPageTransformer和ZoomOutPageTransformer类吗?在这里,可以先分析一下官方的类,在了解之后,就可以照着自定义了。


这里以DepthPageTransformer为例(这里为了兼容Android3.0以下已经做了改动):

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

    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();

        Log.d("测试","view="+view+",position="+position);

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

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

        } else if (position <= 1) { // (0,1], B页position: 1~0.0
            // Fade the page out.
            ViewHelper.setAlpha(view, 1 - position);

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

            // Scale the page down (between MIN_SCALE and 1)
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position)); //scaleFactor: 0.75~1
            ViewHelper.setScaleX(view, scaleFactor);
            ViewHelper.setScaleY(view, scaleFactor);
        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            ViewHelper.setAlpha(view, 0);
        }
    }
}

可以看到在该类里面只有一个方法,包含两个形参,可以在里面添加一行日志,把两个参数都打印出来,看看其在运行时的规律。
这里写图片描述

这里写图片描述

这里写图片描述
上面就是从第一页(在下面暂且设为A页)转到第二页(在下面暂且设为B页)以及打印出的开始部分和最后部分的两个参数的截图。

从两部分日志的截图可以看出,一直是“944d600”和“2f834e39”两个view在交替,当view为“944d600”的时候,对应的position从-0.033333335一直减小到-1.0,而view为“2f834e39”的时候,对应的position从0.96666664一直减小到0.0。

然后看到代码中if-else语句中,可以看到有四部分语句:
1.if (position < -1)//[-Infinity,-1) 对应的为

// This page is way off-screen to the left.
ViewHelper.setAlpha(view, 0);

此时表明view是看不见的(也就是B页是透明的)

2.else if (position <= 0)//[-1,0]对应的为

// Use the default slide transition when moving to the left page
ViewHelper.setAlpha(view, 1);
ViewHelper.setTranslationX(view, 0);
ViewHelper.setScaleX(view, 1);
ViewHelper.setScaleY(view, 1);

此时实际操作的就是A页(position: -1.0~0.0),可以看到代码的逻辑符合前面动态图所展示的A页的动画要求,透明度一直没变,每一时刻水平移动距离为0(注意这里是每一时刻相对的,要知道前面的日志一直是两个view交替打印的,也就是说,在从A页转到B页的过程中,A、B两页的动画一直交替呈现的。如果在这里不理解的话,可以慢慢的想想下面第3点所解释的),且X与Y轴也一直保持原样没有缩放。

3.else if (position <= 1)对应的为

// Fade the page out.
ViewHelper.setAlpha(view, 1 - position);

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

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

此时实际操作的是B页(position: 1.0~0.0),可以看到代码的逻辑同样符合前面动态图所展示的B页的动画要求,透明度慢慢的从0到1,在每一时刻展示的时候都向右水平移动了一段距离,且X与Y轴越来越放大。

4.// (1,+Infinity] 对应的为

// This page is way off-screen to the right.
ViewHelper.setAlpha(view, 0);

也就是说从A页到B页已经完成了,A页看不见了(变成透明的了)

当然了,上面所说的A页、B页是相对的,当你从第二页转到第三页的时候,会打印三个view的信息。


好了,分析完了之后,就动手实现下图中所展示的效果吧:
这里写图片描述

其实也比较简单,if-else语句的第一四部分照抄,只要实现中间两个部分的逻辑即可,(这里实现了兼容Android3.0以下,记得要添加nineoldandroids.jar包):

public class RotateDownPageTansformer implements ViewPager.PageTransformer {
    private static final float MAX_ROTATE=20f;
    private float mRotate;

    //A页角度变化 0 ~ -20
    //B页角度变化 20 ~ 0
    //用Rotation(旋转)实现

    @Override
    public void transformPage(View view, float position) {

        int pageWidth=view.getWidth();

        if (position < -1) {
            ViewHelper.setRotation(view, 0);


        } else if (position <= 0) {//A页

            mRotate=position*MAX_ROTATE;//0 ~ -20

            //设置旋转中心为view的底边的中心位置
            ViewHelper.setPivotX(view, pageWidth/2);
            ViewHelper.setPivotY(view, view.getMeasuredHeight());

/*一般在自定义控件的时候getMeasuredWidth/getMeasuredHeight它的赋值在View的setMeasuredDimension中,所以有时可以在onMeasure方法中看到利用getMeasuredWidth/getMeasuredHeight初始化别的参数。而getWidth/getHeight一直在onLayout完成后才会被赋值。一般情况下,如果都完成了赋值,两者值是相同的。*/

            ViewHelper.setRotation(view, mRotate);

        } else if (position <= 1) {//B页

            mRotate=position*MAX_ROTATE;//20 ~ 0

            //设置旋转中心为view的底边的中心位置
            ViewHelper.setPivotX(view, pageWidth/2);
            ViewHelper.setPivotY(view, view.getMeasuredHeight());

            ViewHelper.setRotation(view, mRotate);

        } else {

            ViewHelper.setRotation(view, 0);
        }
    }
}

好了,然后在MainActivity中代替原来的动画效果即可一下即可:

mViewPager.setPageTransformer(true, new RotateDownPageTansformer());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值