Android --自定义ViewPager切换动画

前言:在做App的Splash页面时有一个漂亮的ViewPager切换动画,不仅能让人耳目一新,而且在开发中面对PM的需求也能做到游刃有余。

先看效果图
这里写图片描述

目录
  1. 自定义ViewPagerTransform方法介绍
  2. 自定义ViewPagerTransform
1:自定义ViewPagerTransform方法介绍

直接上码

private void initViewPager1(){
        vierPage1.setAdapter(new PagerAdapter() {

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

            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView(tvLists.get(position));
            }

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

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

        vierPage1.setPageTransformer(true,new DepthPageTransformer());
    }

private void setData() {
        int[] colors = new int[]{ContextCompat.getColor(this,R.color.green),
                ContextCompat.getColor(this,R.color.red),
           ContextCompat.getColor(this,R.color.mediumvioletred)};

        TextView textView = null;

        for (int i = 0; i < colors.length; i++) {
            textView = new TextView(this);
            textView.setBackgroundColor(colors[i]);
            textView.setText(i+"");
            textView.setGravity(Gravity.CENTER);
            tvLists.add(textView);
        }
    }

这里我给给ViewPager设置3个TextView,分别是0,1,2(为什么是TextView呢,这里后面有用到),分别给了不同的背景色,关键在于

 vierPage1.setPageTransformer(true,new DepthPageTransformer());

DepthPageTransformer

public class DepthPageTransformer implements ViewPager.PageTransformer {
    private static final String TAG = "DepthPageTransformer";
    private static final float MIN_SCALE = 0.75f;
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
   /**
     * position取值特点:
     * 假设页面从0~1,则:
     * 第一个页面position变化为[0,-1] 当前的View
     * 第二个页面position变化为[1,0]  进入的View
     *
     * @param page
     * @param position
     */
    @Override
    public void transformPage(View view, float position) {
        Log.d(TAG,((TextView)view).getText() + "___" + position);
        int pageWidth = view.getWidth();

        if (position < -1) { // [-Infinity,-1) 不可见的View
            view.setAlpha(0);

        } else if (position <= 0) { // [-1,0]  当前的View

            view.setAlpha(1);
            view.setTranslationX(0);
            view.setScaleX(1);
            view.setScaleY(1);

        } else if (position <= 1) { // (0,1] 进入的View 

            view.setAlpha(1 - position);
            view.setTranslationX(pageWidth * -position);
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

        } else {  (1,+Infinity] //不可见的View
            view.setAlpha(0);
        }
    }
}

要使用自定义切换效果必须实现ViewPager.PageTransformer
它的transformerPage 方法虽然有注释,但是不是很好理解,这时候TextView用处就上场了,来看看Log打印出来的东西

页面进入的时候:

05-24 01:46:21.456 1645-1645/norton.animademo D/DepthPageTransformer: 0___0.0
05-24 01:46:21.456 1645-1645/norton.animademo D/DepthPageTransformer: 1___1.0

由 0 ->1
这里写图片描述

05-24 01:46:25.327 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.052083332
05-24 01:46:25.327 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.9479167
05-24 01:46:25.345 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.24722221
05-24 01:46:25.345 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.75277776
05-24 01:46:25.366 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.52847224
05-24 01:46:25.366 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.47152779
05-24 01:46:25.380 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.77708334
05-24 01:46:25.380 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.22291666
05-24 01:46:25.394 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.90833336
05-24 01:46:25.394 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.09166667
05-24 01:46:25.411 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.9763889
05-24 01:46:25.411 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.023611112
05-24 01:46:25.428 1645-1645/norton.animademo D/DepthPageTransformer: 0___-0.99722224
05-24 01:46:25.428 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.0027777778
05-24 01:46:25.444 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.0
05-24 01:46:25.444 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.0

由1->2
这里写图片描述

05-24 01:49:49.110 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.09791667
05-24 01:49:49.110 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.90208334
05-24 01:49:49.110 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.0979167
05-24 01:49:49.127 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.37013888
05-24 01:49:49.127 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.6298611
05-24 01:49:49.127 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.3701389
05-24 01:49:49.143 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.58958334
05-24 01:49:49.143 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.41041666
05-24 01:49:49.143 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.5895833
05-24 01:49:49.160 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.84930557
05-24 01:49:49.160 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.15069444
05-24 01:49:49.160 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.8493055
05-24 01:49:49.180 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.9611111
05-24 01:49:49.180 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.03888889
05-24 01:49:49.180 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.9611111
05-24 01:49:49.196 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.99375
05-24 01:49:49.196 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.00625
05-24 01:49:49.196 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.99375
05-24 01:49:49.212 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.99930555
05-24 01:49:49.212 1645-1645/norton.animademo D/DepthPageTransformer: 2___6.9444446E-4
05-24 01:49:49.212 1645-1645/norton.animademo D/DepthPageTransformer: 0___-1.9993056
05-24 01:49:49.226 1645-1645/norton.animademo D/DepthPageTransformer: 1___-1.0
05-24 01:49:49.226 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.0
05-24 01:49:49.229 1645-1645/norton.animademo D/DepthPageTransformer: 0___-2.0

由2->1
这里写图片描述

05-24 01:50:20.677 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.9444444
05-24 01:50:20.677 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.055555556
05-24 01:50:20.694 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.68680555
05-24 01:50:20.694 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.31319445
05-24 01:50:20.710 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.4173611
05-24 01:50:20.710 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.58263886
05-24 01:50:20.720 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.33402777
05-24 01:50:20.720 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.66597223
05-24 01:50:20.727 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.23055555
05-24 01:50:20.727 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.76944447
05-24 01:50:20.743 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.06736111
05-24 01:50:20.743 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.9326389
05-24 01:50:20.760 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.014583333
05-24 01:50:20.760 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.98541665
05-24 01:50:20.777 1645-1645/norton.animademo D/DepthPageTransformer: 1___-0.0013888889
05-24 01:50:20.777 1645-1645/norton.animademo D/DepthPageTransformer: 2___0.9986111
05-24 01:50:20.794 1645-1645/norton.animademo D/DepthPageTransformer: 1___0.0
05-24 01:50:20.795 1645-1645/norton.animademo D/DepthPageTransformer: 2___1.0

日志出来这个东西就很好解释了
可以看见,transformPage这个方法当中的View的值进入,退出的View 来回依次出现的;
前面的数字就是显示的对应的TextView(这时知道TextView的用处了吧);
对切换而言是有2个对象的,一个是进入的,一个是退出的。
退出的View 的position 是一个 [0,-1] 的值;
进入的View 的position 是一个 [1,0] 的值;
搞懂View和position的关系,现在无论是自定义动画或者自定义View,都很好处理了。

2. 自定义ViewPagerTransform

下面来看看一个ViewPagerTransforms的开源项目
https://github.com/ToxicBakery/ViewPagerTransforms当中的一些炫酷效果
这里写图片描述

public class CudeOutTransformer implements ViewPager.PageTransformer {
    @Override
    public void transformPage(View page, float position) {

        page.setPivotX(position < 0f ? page.getWidth() : 0f);
        page.setPivotY(page.getHeight() * 0.5f);
        page.setRotationY(90f * position);

        page.setAlpha(position <= -1f || position >= 1f ? 0f : 1f); // 看不见的view

    }
}

公式很简单就不多解释了,这里主要是用了一些三元运算符,
轴转动和旋转动画组合起来效果还不错。

这里写图片描述

public class ZoomInTransformer implements ViewPager.PageTransformer{

    @Override
    public void transformPage(View view, float position) {
        final float width = view.getWidth();

        view.setRotationX(0);
        view.setRotationY(0);
        view.setRotation(0);
        view.setScaleX(1);
        view.setScaleY(1);
        view.setPivotX(0);
        view.setPivotY(0);
        view.setTranslationY(0);
        view.setTranslationX(-width * position);

        final float scale = position < 0 ? position + 1f : Math.abs(1f - position);
        view.setScaleX(scale);
        view.setScaleY(scale);
        view.setPivotX(view.getWidth() * 0.5f);
        view.setPivotY(view.getHeight() * 0.5f);
        view.setAlpha(position < -1f || position > 1f ? 0f : 1f - (scale - 1f)); //不可见View
    }
}

这个代码看着挺多的,其实很简单,主要是一个把View移动到中心位置,然后进入的View放大,退出的View缩小。

总结:其实自定义Viewpager的Transform搞清楚
退出的View 的position 是一个 [0,-1] 的值;
进入的View 的position 是一个 [1,0] 的值;
这一点,就很好处理了,动画都是有过度值的,由position确定View,再给View设置一个动画效果,难点在于~ 数学要好!数学要好!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值