以下内容来自Android Training,本人在此基础上作一些个人实践和记录,以便参考
页面间的切换很常见,友好的过渡页面的切换是体验的一个重要部分,下面用ViewPager为例,实现页面切换的动画效果.
普通的页面切换:
自定义切换动画
- 创建一个子类实现ViewPager.PageTransformer接口
- 调用ViewPager的setPageTransformer()方法设置自定义的ViewPager.PageTransformer
详细说明:
ViewPager.PageTransformer中只有一个方法transformPage(View page, float position),每次页面有移动时,邻近的page都会调用这个方法(不过我看源码里面是遍历所有的child,每个都调用一次)
// ViewPager.java
@CallSuper
protected void onPageScrolled(int position, float offset, int offsetPixels) {
...
// mPageTransformer持有我们new的自定义的PageTransformer的对象
if (mPageTransformer != null) {
final int scrollX = getScrollX();
final int childCount = getChildCount();
// 遍历所有的child
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.isDecor) continue;
final float transformPos = (float) (child.getLeft() - scrollX) / getClientWidth();
// 回调transformPage()方法
mPageTransformer.transformPage(child, transformPos);
}
}
mCalledSuper = true;
}
然后我们可以在自定义的PageTransformer类中的transformPage()方法,根据判断position参数来对相应的page来进行相应的操作,对于postion这个参数,指示者page相对于中间的位置,如源码写的公式:
transformPos = (float) (child.getLeft() - scrollX) / getClientWidth();
如图:
自定义1 -- Zoom-out page transformer
效果:
代码:
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) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} 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(0);
}
}
}
自定义2 -- Depth page transformer
代码:
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) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
// 这一步很重要,设置了这个才有浮出的效果,否则效果是从左右进出,而不是上下
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);
}
}
}
自定义3 -- Rotate page transformer
效果:
代码:
public class RotatePageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f;
@Override
public void transformPage(View page, float position) {
if (position < -1 || position > 1) {
page.setAlpha(0);
} else {
page.setRotation(360 * position);
// Fade the page out.
page.setAlpha(1 - Math.abs(position));
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
page.setScaleX(scaleFactor);
page.setScaleY(scaleFactor);
}
}
}
Notice
- ViewPager.PageTransformer,这个类对于ViewPager还是挺实用的,记住用