ViewPager<第二篇>:实现翻页动画
为ViewPager提供动画效果,显然,使得UI变得用户更加友好,所以它的作用可想而知。
ViewPager为我们提供了setPageTransformer
方法可以设置切换动画
public void setPageTransformer(boolean reverseDrawingOrder, @Nullable PageTransformer transformer)
reverseDrawingOrder:若为true,属性动画倒序播放;若为false,则正序播放;
transformer:为每个页面设置切换动画;
为了实现ViewPager的切换动画,必须自定义DepthPageTransformer
,基本代码如下:
public class MyPageTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
}
}
创建一个MyPageTransformer
类,实现ViewPager.PageTransformer
,重写方法transformPage
,transformPage
方法有两个参数,分别是page
、position
。
-
page
是添加到ViewPager中的view。 -
position
并不是ViewPager的页码,而是代表切换页面的角标。当切换页面之后,当前页的position
值始终为0,左边第一个页面为-1,右边第一个页面为1。(补充:左边第二个也页面为-2,右边第二个页面为2)。
ViewPager的切换动画总是在transformPage
方法中实现的,那么现在就贴出整理之后的案例吧。
【案例一】
折叠翻页特效
效果演示:

代码如下:
public class AccordionTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
//只对[-1,1]之间处理,超过范围将属性设置为初始值
if (position < -1) { // [-Infinity,-1)
page.setPivotX(0f);
page.setScaleX(1f);
page.setTranslationX(0);
} else if (position <= 0) { // [-1,0]
page.setPivotX(0f);
page.setTranslationX(-position * page.getWidth());
page.setScaleX(position + 1);
} else if (position <= 1) { // (0,1]
page.setPivotX(page.getWidth());
page.setTranslationX(-position * page.getWidth());
page.setScaleX(1-position);
} else { // (1,+Infinity]
page.setPivotX(0f);
page.setScaleX(1f);
page.setTranslationX(0);
}
}
}
【案例二】
前台到后台,后台到前台的切换动画
效果演示:

代码如下:
public class BackgroundAndForegroundTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
//只对[-1,1]之间处理,超过范围将属性设置为初始值
if (position < -1) { // [-Infinity,-1)
page.setScaleX(1f);
page.setScaleY(1f);
page.setPivotX(0f);
page.setPivotY(0f);
page.setTranslationX(0);
} else if (position <= 0) { // [-1,0]
page.setPivotX(page.getWidth() * 0.5f);
page.setPivotY(page.getHeight() * 0.5f);
page.setScaleX(1 + position);
page.setScaleY(1 + position);
page.setTranslationX(-page.getWidth() * position * 0.5f);
} else if (position <= 1) { // (0,1]
page.setPivotX(page.getWidth() * 0.5f);
page.setPivotY(page.getHeight() * 0.5f);
page.setScaleX(1 - position);
page.setScaleY(1 - position);
page.setTranslationX(page.getWidth() * position * 0.5f);
} else { // (1,+Infinity]
page.setScaleX(1f);
page.setScaleY(1f);
page.setPivotX(0f);
page.setPivotY(0f);
page.setTranslationX(0);
}
}
}
【案例三】
立方体内部切换动画
效果演示:

代码如下:
public class CubeInTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
//只对[-1,1]之间处理,超过范围将属性设置为初始值
page.setCameraDistance(page.getWidth() * 20);
if (position < -1) { // [-Infinity,-1)
page.setPivotX();
page.setPivotY(0f);
page.setRotationY(0);
} else if (position <= 0) { // [-1,0]
page.setPivotX(page.getWidth());
page.setPivotY(0f);
page.setRotationY(-90f * position);
} else if (position <= 1) { // (0,1]
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(-90f * position);
} else { // (1,+Infinity]
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
}
}
}
【案例四】
立方体外部切换动画
效果演示:

代码如下:
public class CubeInTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
//只对[-1,1]之间处理,超过范围将属性设置为初始值
page.setCameraDistance(page.getWidth() * 20);
if (position < -1) { // [-Infinity,-1)
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
} else if (position <= 0) { // [-1,0]
page.setPivotX(page.getWidth());
page.setPivotY(0f);
page.setRotationY(-90f * position);
} else if (position <= 1) { // (0,1]
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(-90f * position);
} else { // (1,+Infinity]
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
}
}
}
【案例五】
深度页面切换
效果演示:

代码如下:
public class DepthPageTransformer implements ViewPager.PageTransformer {
private static float MIN_SCALE = 0.75f;
@Override
public void transformPage(@NonNull View page, float position) {
int pageWidth = page.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
page.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
page.setAlpha(1);
page.setTranslationX(0);
page.setScaleX(1);
page.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
page.setAlpha(1 - position);
// Counteract the default slide transition
page.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
page.setScaleX(scaleFactor);
page.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
page.setAlpha(0);
}
}
}
【案例六】
抽屉式页面切换
效果演示:

代码如下:
public class DrawerTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
//只对[-1,1]之间处理,超过范围将属性设置为初始值
page.setCameraDistance(page.getWidth() * 20);
if (position < -1) { // [-Infinity,-1)
page.setTranslationX(0);
} else if (position <= 0) { // [-1,0]
page.setTranslationX(0);
} else if (position <= 1) { // (0,1]
page.setTranslationX(-page.getWidth() / 2 * position);
} else { // (1,+Infinity]
page.setTranslationX(0);
}
}
}
【案例七】
横向开关页面切换
效果演示:

代码如下:
public class FlipHorizontalTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
//只对[-1,1]之间处理,超过范围将属性设置为初始值
if (position < -1) { // [-Infinity,-1)
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
} else if (position <= 1) { // (0,1]
float rotation = 180f * position;
page.setAlpha(rotation > 90f || rotation < -90f ? 0f : 1f);
page.setPivotX(page.getWidth() * 0.5f);
page.setPivotY(page.getHeight() * 0.5f);
page.setRotationY(rotation);
page.setTranslationX(-page.getWidth() * position);
} else { // (1,+Infinity]
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
}
page.setVisibility(position > -0.5f && position < 0.5f ? View.VISIBLE : View.INVISIBLE);
}
}
【案例八】
纵向开关页面切换
效果演示:

代码如下:
public class FlipVerticalTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
if (position < -1) { // [-Infinity,-1)
page.setAlpha(0f);
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationX(0f);
page.setTranslationX(0f);
} else if (position <= 1) { // [-1,0]
float rotation = -180f * position;
page.setAlpha(rotation > 90f || rotation < -90f ? 0f : 1f);
page.setPivotX(page.getWidth() * 0.5f);
page.setPivotY(page.getHeight() * 0.5f);
page.setRotationX(rotation);
page.setTranslationX(-page.getWidth() * position);
}else { // (1,+Infinity]
page.setAlpha(0f);
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationX(0f);
page.setTranslationX(0f);
}
page.setVisibility(position > -0.5f && position < 0.5f ? View.VISIBLE : View.INVISIBLE);
}
}
【案例九】
向下旋转页面切换
效果演示:

代码如下:
public class RotateDownTransformer implements ViewPager.PageTransformer {
private static float ROT_MOD = 18.75f;
@Override
public void transformPage(@NonNull View page, float position) {
if (position < -1) { // [-Infinity,-1)
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
} else if (position <= 1) { // [-1,0]
float width = page.getWidth();
float height = page.getHeight();
float rotation = ROT_MOD * position;
page.setPivotX(width * 0.5f);
page.setPivotY(height);
page.setRotation(rotation);
} else { // (1,+Infinity]
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
}
}
}
【案例十】
向上旋转页面切换
效果演示:

代码如下:
public class RotateUpTransformer implements ViewPager.PageTransformer {
private static float ROT_MOD = -15f;
@Override
public void transformPage(@NonNull View page, float position) {
if (position < -1) { // [-Infinity,-1)
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
} else if (position <= 1) { // [-1,0]
float width = page.getWidth();
float rotation = ROT_MOD * position;
page.setPivotX(width * 0.5f);
page.setPivotY(0f);
page.setRotation(rotation);
} else { // (1,+Infinity]
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
}
}
}
【案例十一】
缩放效果的页面切换
效果演示:

代码如下:
public class ScaleInOutTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
if (position < -1) { // [-Infinity,-1)
page.setPivotX(0f);
page.setPivotY(0f);
page.setTranslationX(0f);
page.setScaleX(0f);
page.setScaleY(0f);
} else if (position <= 0) { // [-1,0]
page.setPivotX(0);
page.setPivotY(page.getHeight() / 2f);
page.setTranslationX(-page.getWidth() * position);
page.setScaleX(1f + position);
page.setScaleY(1f + position);
} else if (position <= 1) { // (0,1]
page.setPivotX(page.getWidth());
page.setPivotY(page.getHeight() / 2f);
page.setTranslationX(-page.getWidth() * position);
page.setScaleX(1f - position);
page.setScaleY(1f - position);
} else { // (1,+Infinity]
page.setPivotX(0f);
page.setPivotY(0f);
page.setTranslationX(0f);
page.setScaleX(0f);
page.setScaleY(0f);
}
}
}
【案例十二】
堆叠页面切换
效果演示:

代码如下:
public class StackTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
if (position < -1) { // [-Infinity,-1)
page.setTranslationX(0f);
} else if (position <= 0) { // [-1,0]
page.setTranslationX(0f);
} else if (position <= 1) { // (0,1]
page.setTranslationX(-page.getWidth() * position);
} else { // (1,+Infinity]
page.setTranslationX(0f);
}
}
}
【案例十三】
纪念牌页面切换
效果演示:

代码如下:
public class TabletTransformer implements ViewPager.PageTransformer {
private Matrix OFFSET_MATRIX = new Matrix();
private Camera OFFSET_CAMERA = new Camera();
private float[] OFFSET_TEMP_FLOAT = new float[2];
private float ROT_MOD = 30f;
protected float getOffsetXForRotation(float degrees, int width, int height) {
OFFSET_MATRIX.reset();
OFFSET_CAMERA.save();
OFFSET_CAMERA.rotateY(Math.abs(degrees));
OFFSET_CAMERA.getMatrix(OFFSET_MATRIX);
OFFSET_CAMERA.restore();
OFFSET_MATRIX.preTranslate(-width * 0.5f, -height * 0.5f);
OFFSET_MATRIX.postTranslate(width * 0.5f, height * 0.5f);
OFFSET_TEMP_FLOAT[0] = width;
OFFSET_TEMP_FLOAT[1] = height;
OFFSET_MATRIX.mapPoints(OFFSET_TEMP_FLOAT);
return (width - OFFSET_TEMP_FLOAT[0]) * (degrees > 0.0f ? 1.0f : -1.0f);
}
@Override
public void transformPage(@NonNull View page, float position) {
if (position < -1) { // [-Infinity,-1)
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
page.setTranslationX(0);
} else if (position <= 1) { // [-1,0]
float rotation = position < 0 ? ROT_MOD : -ROT_MOD;
float rotationY = rotation * Math.abs(position);
page.setPivotX(page.getWidth() * 0.5f);
page.setPivotY(0f);
page.setRotationY(rotationY);
page.setTranslationX(getOffsetXForRotation(rotationY, page.getWidth(), page.getHeight()));
} else { // (1,+Infinity]
page.setPivotX(0f);
page.setPivotY(0f);
page.setRotationY(0);
page.setTranslationX(0);
}
}
}
【案例十四】
内部缩放页面切换
效果演示:

代码如下:
public class ZoomInTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
if (position < -1) { // [-Infinity,-1)
page.setScaleX(0);
page.setScaleY(0);
page.setTranslationX(0);
page.setPivotX(0);
page.setPivotY(0);
page.setAlpha(0);
} else if (position <= 0) { // [-1,0]
page.setScaleX(position + 1f);
page.setScaleY(position + 1f);
page.setTranslationX(-page.getWidth() * position);
page.setPivotX(page.getWidth() * 0.5f);
page.setPivotY(page.getHeight() * 0.5f);
page.setAlpha(1f - position);
} else if (position <= 1) { // (0,1]
page.setScaleX(1f - position);
page.setScaleY(1f - position);
page.setTranslationX(-page.getWidth() * position);
page.setPivotX(page.getWidth() * 0.5f);
page.setPivotY(page.getHeight() * 0.5f);
page.setAlpha(1f + position);
} else { // (1,+Infinity]
page.setScaleX(0);
page.setScaleY(0);
page.setTranslationX(0);
page.setPivotX(0);
page.setPivotY(0);
page.setAlpha(0);
}
}
}
【案例十五】
外部缩放页面切换
效果演示:

代码如下:
public class ZoomOutTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View page, float position) {
if (position < -1) { // [-Infinity,-1)
page.setScaleX(1f);
page.setScaleY(1f);
page.setTranslationX(0f);
page.setPivotX(0f);
page.setPivotY(0f);
page.setAlpha(0f);
} else if (position <= 0) { // [-1,0]
float scale = 1f -position;
page.setScaleX(scale);
page.setScaleY(scale);
page.setTranslationX(-page.getWidth() * position);
page.setPivotX(page.getWidth() * 0.5f);
page.setPivotY(page.getHeight() * 0.5f);
page.setAlpha(1f + position);
if (position == -1f){
page.setTranslationX(page.getWidth() * -1);
}
} else if (position <= 1) { // (0,1]
float scale = 1f + position;
page.setScaleX(scale);
page.setScaleY(scale);
page.setTranslationX(-page.getWidth() * position);
page.setPivotX(page.getWidth() * 0.5f);
page.setPivotY(page.getHeight() * 0.5f);
page.setAlpha(1f - position);
} else { // (1,+Infinity]
page.setScaleX(1f);
page.setScaleY(1f);
page.setTranslationX(0f);
page.setPivotX(0f);
page.setPivotY(0f);
page.setAlpha(0f);
}
}
}
【案例十六】
缩小页面的页面切换
当在相邻页面之间滚动时,此页面转换器将缩小和淡入页面。当一个页面靠近中心时,它会变回原来的大小并逐渐消失。
效果演示:

代码如下:
public class ZoomOutSlideTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.85f;
private static final float MIN_ALPHA = 0.5f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0f);
} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA +
(scaleFactor - MIN_SCALE) /
(1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0f);
}
}
}
以上16中翻页效果的实现代码送给大家。
[本章完...]