Android动画之页面切换

以下内容来自Android Training,本人在此基础上作一些个人实践和记录,以便参考

页面间的切换很常见,友好的过渡页面的切换是体验的一个重要部分,下面用ViewPager为例,实现页面切换的动画效果.

普通的页面切换:

Android动画之页面切换_第1张图片
pager_no by keith

自定义切换动画

  1. 创建一个子类实现ViewPager.PageTransformer接口
  2. 调用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();

如图:

Android动画之页面切换_第2张图片
page_transformer_position.png

自定义1 -- Zoom-out page transformer

效果:

Android动画之页面切换_第3张图片
zoom_out by keith

代码:

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

pager_depth by keith

代码:

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

效果:

Android动画之页面切换_第4张图片
pager_rotate by keith

代码:

    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还是挺实用的,记住用

Reference

  1. Using ViewPager for Screen Slides

你可能感兴趣的:(Android动画之页面切换)