android viewpager切换动画-pageTransformer

想使用viewpager的切换动画,源于一个叫sun的应用,想模仿3d转场的效果。

setPageTransformer

ViewPager提供了一个setPageTransformer,用于设置ViewPager切换时的动画效果。如下:

1
viewpagerMain.setPageTransformer(true,new CubeOutTransformer());

注意:并不兼容3.0以下的版本的,会没有任何效果。
源码中有以下的判断

1
if (Build.VERSION.SDK_INT >= 11) {

其中设置动画的CubeOutTransformer需要实现viewpager.PageTransformer这个接口

1
2
3
4
5
6
7
8
9
public interface PageTransformer {  
/**
...
* @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.
*/

public void transformPage(View page, float position);
}

根据解释可以知道:
position的可能性的值有,其实从官方示例的注释就能看出:

  • [-Infinity,-1) 已经看不到了
  • (1,+Infinity] 已经看不到了
  • [-1,1]

重点看[-1,1]这个区间 , 其他两个的View都已经看不到了。即:

假设现在ViewPager在A页现在滑出B页,则:

  • A页的position变化就是( 0, -1]
  • B页的position变化就是[ 1 , 0 ]

下面进行设置一个案例:

下面我们分析代码:

我们设置View的旋转中心为:(固定旋转轴)

1
2
ViewHelper.setPivotX(view, view.getMeasuredWidth() * 0.5f);
ViewHelper.setPivotY(view, view.getMeasuredHeight());

依然是ViewPager在A页现在滑出B页

那么A页应当在滑动过程中0度到-20度的偏移,B页应当在滑动过程中+20度到0度的偏移

结合

A页的position变化就是( 0, -1]

B页的position变化就是[ 1 , 0 ]

那么旋转的角度即:mRot = (20 * position); A页 mRot :0 ,~ -20 ; B页 mRot :20 ~ 0 ;

瞬间觉得好简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.zhy.view;  

import com.nineoldandroids.view.ViewHelper;

import android.annotation.SuppressLint;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.View;

public class RotateDownPageTransformer implements ViewPager.PageTransformer
{


private static final float ROT_MAX = 20.0f;
private float mRot;



public void transformPage(View view, float position)
{


Log.e("TAG", view + " , " + position + "");

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

} else if (position <= 1) // a页滑动至b页 ; a页从 0.0 ~ -1 ;b页从1 ~ 0.0
{ // [-1,1]

// Modify the default slide transition to shrink the page as well
if (position < 0)
{

mRot = (ROT_MAX * position);
ViewHelper.setPivotX(view, view.getMeasuredWidth() * 0.5f);
ViewHelper.setPivotY(view, view.getMeasuredHeight());
ViewHelper.setRotation(view, mRot);
} else
{

mRot = (ROT_MAX * position);
ViewHelper.setPivotX(view, view.getMeasuredWidth() * 0.5f);
ViewHelper.setPivotY(view, view.getMeasuredHeight());
ViewHelper.setRotation(view, mRot);
}

// Scale the page down (between MIN_SCALE and 1)

// Fade the page relative to its size.

} else
{ // (1,+Infinity]
// This page is way off-screen to the right.
ViewHelper.setRotation(view, 0);
}
}
}

以上缩写均摘抄于:Android 实现个性的ViewPager切换动画 实战PageTransformer(兼容Android3.0以下),这里面用到向下兼容的,使用 NineOldAndroids来达到当sdk<11的时候仍然有效果。

另外介绍一个这些效果的库:
ViewPagerTransforms,包含各种你想要的效果。

注意这里有一个错误
上面的情况是activity+viewpager,但当Fragment和ViewPager一起交错使用时,出现以下异常:

Recursive entry to executePendingTransactions
解决方法:看如下修改

1
2
3
4
将:
BgManagerAdapter bgManagerAdapter=new BgManagerAdapter(getActivity().getFragmentManager(),fragments);
改成:
BgManagerAdapter bgManagerAdapter=new BgManagerAdapter(this.getChildFragmentManager(),fragments);

即:activity.getFragmentManager()改成fragment.getChildFragmentManager()