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設置一個動畫效果,難點在於~ 數學要好!數學要好!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章