最基本的 ViewPager 已经可以创建出来了,左右滑动实现 View 之间的转换,但是转换模式是不是有些单调?
Android 提供了 setPageTransformer
方法来设置 ViewPager 的滑动动画:
PageTransformer 是一个接口,我们需要自己去实现该接口,去自定义滑动动画:
public class CustomPagerTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(View page, float position) {
}
}
我们实现 PageTransformer 接口需要重写 transformPage 方法,这个方法有两个参数:
当我们滑动一个 ViewPager 的时候,当前 View “退出舞台”,另一个 View 粉墨登场,transformPage 方法中的 view 参数,就代表着这两个 View。
详细的讲一下 position 这个值的作用。
假如说我们 ViewPager 有三个页面:
使用 Log 会更直观的看清这个 position 到底是何方神圣。
我们可以看到,当向左滑动时:
当向右滑动时:
所以我们可以总结 position 主要有三个“极限值”:
整个滑动的过程中,每个 View 的 position 值都是随着滑动动态改变的,这个不就正好可以通过修改 View 的属性,来实现进出动画效果了么。
官方并没有提供现成的 PagerTransformer 实现类,不过在官方培训部分有两个例子可以供我们参考:
先上效果图:
来看一下代码:
public class ZoomOutPageTransformer 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) {
//获取 View 的宽/高
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) {
// 如果 position < -1,则表明该 View 位置并不在当前显示 View 的左边,所以设置其透明度为 0,事实上,就算不设置,也没有关系。
view.setAlpha(0);
} else if (position <= 1) { //position<=1 表示向左滑动,当前View从0向-1过度,右边的View 从1向0过度。
//确定缩放因子,最小为 0.85f
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);
}
// 设置缩放动画
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// 同时设置透明度
view.setAlpha(MIN_ALPHA +
(scaleFactor - MIN_SCALE) /
(1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else {
//position >1 的 ,同样也可以忽略
view.setAlpha(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();
if (position < -1) {
// 不用理会
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// position<=0,表示View从左边划入或者划出到左边。
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) {
// position <= 1,表示View从右边进入或者划出到右边。
view.setAlpha(1 - position); //右边进入或退出的透明度,进入时透明度越来越大,退出时透明度越来越小。
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}