[关闭]
@xujun94 2016-08-21T15:15:48.000000Z 字数 5844 阅读 1405

Android打造不一样的新手引导页面(二)


本系列主要分为两篇博客

Android打造不一样的新手引导页面(一)

Android打造不一样的新手引导页面(二)

关于页面导航器的,可以查看我的这一篇博客仿网易新闻的顶部导航指示器

上一篇博客主要讲解怎样自定义一个CirclePageIndicator控件

这篇博客主要讲解怎样更改ViewPager切换的效果。

首先我们先来看一下默认的ViewPager的切换效果,感觉是不是很普通,因为大多数时候我们经常没有用到ViewPager的动画切换效果 ,这种想过见多了,也就觉得平淡了

下面我们来看一下我们自己实现的ViewPager页面的 切换效果,总共有 四种不同的样式

实现原理说明

其实要实现上述的 效果非常简单,只需要以下几行代码,就搞定了。

  1. viewpager.setPageTransformer(true, new ViewPager.PageTransformer() {
  2. @Override
  3. public void transformPage(View page, float position) {
  4. // do transformation here
  5. }
  6. });

Google官方关于两个参数的解释是

reverseDrawingOrder boolean: true if the supplied PageTransformer requires page views to be drawn from last to first instead of first to last.

transformer ViewPager.PageTransformer: PageTransformer that will modify each page's animation properties

第一个布尔型参数表示的意思就是在两个页面切换产生动画效果时候是否要反转一下让下一个页面在上一个页面底下,因为ViewPager默认下一个页面是绘制在上一个页面的上面,这里一般传入true。

第二次参数才是重点,这里实现了PageTransformer接口,然后我们所有需要的动画效果都在transformPage这个接口方法里面实现,现在我们来看看这个方法。

transformPage void transformPage (View page, 
                float position)

page View: Apply the transformation to this page
position

float: 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.

下面我们借用一张图片来解释position的变化

页面切换

假设当前我们屏幕中的页面是B:

解释完这些参数是什么意思,下面让我们来看一下我们是怎样实现的

Google的两个例子

首先我们先来看一下官方的两个例子,地址是:http://developer.android.com/training/animation/screen-slide.html

ZoomOutPageTransformer

  1. public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
  2. private static final float MIN_SCALE = 0.85f;
  3. private static final float MIN_ALPHA = 0.5f;
  4. public void transformPage(View view, float position) {
  5. int pageWidth = view.getWidth();
  6. int pageHeight = view.getHeight();
  7. if (position < -1) { // [-Infinity,-1)
  8. // This page is way off-screen to the left.
  9. view.setAlpha(0);
  10. } else if (position <= 1) { // [-1,1]
  11. // Modify the default slide transition to shrink the page as well
  12. float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
  13. float vertMargin = pageHeight * (1 - scaleFactor) / 2;
  14. float horzMargin = pageWidth * (1 - scaleFactor) / 2;
  15. if (position < 0) {
  16. view.setTranslationX(horzMargin - vertMargin / 2);
  17. } else {
  18. view.setTranslationX(-horzMargin + vertMargin / 2);
  19. }
  20. // Scale the page down (between MIN_SCALE and 1)
  21. view.setScaleX(scaleFactor);
  22. view.setScaleY(scaleFactor);
  23. // Fade the page relative to its size.
  24. view.setAlpha(MIN_ALPHA +
  25. (scaleFactor - MIN_SCALE) /
  26. (1 - MIN_SCALE) * (1 - MIN_ALPHA));
  27. } else { // (1,+Infinity]
  28. // This page is way off-screen to the right.
  29. view.setAlpha(0);
  30. }
  31. }
  32. }

运行到上述的代码,效果图如下

从上述效果图可以看到,页面切换的时候,主要是页面大小的 变化,水平移动距离的变化以及透明度的变化,这些也可以从代码中体现回来,我们主要关心[-1,1]的时候就OK,因为在[-Infinity,-1)和(1,+Infinity]的时候是不可见的。

  1. if (position < -1) { // [-Infinity,-1)
  2. // This page is way off-screen to the left.
  3. page.setAlpha(0);
  4. } else if (position <= 1) { // [-1,1]
  5. // Modify the default slide transition to shrink the page as well
  6. float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
  7. float vertMargin = pageHeight * (1 - scaleFactor) / 2;
  8. float horzMargin = pageWidth * (1 - scaleFactor) / 2;
  9. if (position < 0) {
  10. page.setTranslationX(horzMargin - vertMargin / 2);
  11. } else {
  12. page.setTranslationX(-horzMargin + vertMargin / 2);
  13. }
  14. // Scale the page down (between MIN_SCALE and 1)
  15. page.setScaleX(scaleFactor);
  16. page.setScaleY(scaleFactor);
  17. // Fade the page relative to its size.
  18. page.setAlpha(MIN_ALPHA +
  19. (scaleFactor - MIN_SCALE) /
  20. (1 - MIN_SCALE) * (1 - MIN_ALPHA));
  21. } else { // (1,+Infinity]
  22. // This page is way off-screen to the right.
  23. page.setAlpha(0);
  24. }

DepthPageTransformer

  1. public class DepthPageTransformer implements ViewPager.PageTransformer {
  2. private static final float MIN_SCALE = 0.75f;
  3. public void transformPage(View view, float position) {
  4. int pageWidth = view.getWidth();
  5. if (position < -1) { // [-Infinity,-1)
  6. // This page is way off-screen to the left.
  7. view.setAlpha(0);
  8. } else if (position <= 0) { // [-1,0]
  9. // Use the default slide transition when moving to the left page
  10. view.setAlpha(1);
  11. view.setTranslationX(0);
  12. view.setScaleX(1);
  13. view.setScaleY(1);
  14. } else if (position <= 1) { // (0,1]
  15. // Fade the page out.
  16. view.setAlpha(1 - position);
  17. // Counteract the default slide transition
  18. view.setTranslationX(pageWidth * -position);
  19. // Scale the page down (between MIN_SCALE and 1)
  20. float scaleFactor = MIN_SCALE
  21. + (1 - MIN_SCALE) * (1 - Math.abs(position));
  22. view.setScaleX(scaleFactor);
  23. view.setScaleY(scaleFactor);
  24. } else { // (1,+Infinity]
  25. // This page is way off-screen to the right.
  26. view.setAlpha(0);
  27. }
  28. }
  29. }

运行上述代码以后,可以看到的变化是


下面来看一下我们自己实现的两个例子

看到上述图以后,仔细分析可以看到在我们滑动的时候主要是旋转角度的 变化,并且Y轴旋转中心是页面的中心点,当position<0的时候,X轴的中心是view.getWidth,当position>0的时候,x轴的中心是0,代码如下。

  1. public class CubeOutTransformer extends BaseTransformer {
  2. @Override
  3. protected void onTransform(View view, float position) {
  4. view.setPivotX(position < 0f ? view.getWidth() : 0f);
  5. view.setPivotY(view.getHeight() * 0.5f);
  6. view.setRotationY(90f * position);
  7. }
  8. @Override
  9. public boolean isPagingEnabled() {
  10. return true;
  11. }
  12. }

TableTransformer

  1. public class TableTransformer extends BaseTransformer {
  2. private static final Matrix OFFSET_MATRIX = new Matrix();
  3. private static final Camera OFFSET_CAMERA = new Camera();
  4. private static final float[] OFFSET_TEMP_FLOAT = new float[2];
  5. private static final float minScale=0.6f;
  6. @Override
  7. protected void onTransform(View view, float position) {
  8. final float rotation = (position < 0 ? 30f : -30f) * Math.abs(position);
  9. view.setTranslationX(getOffsetXForRotation(rotation, view.getWidth(), view.getHeight()));
  10. view.setPivotX(view.getWidth() * 0.5f);
  11. view.setPivotY(0);
  12. view.setRotationY(rotation);
  13. float scaleX=Math.max(1-Math.abs(position),minScale);
  14. view.setScaleX(scaleX);
  15. }
  16. protected static final float getOffsetXForRotation(float degrees, int width, int height) {
  17. OFFSET_MATRIX.reset();
  18. OFFSET_CAMERA.save();
  19. OFFSET_CAMERA.rotateY(Math.abs(degrees));
  20. OFFSET_CAMERA.getMatrix(OFFSET_MATRIX);
  21. OFFSET_CAMERA.restore();
  22. OFFSET_MATRIX.preTranslate(-width * 0.5f, -height * 0.5f);
  23. OFFSET_MATRIX.postTranslate(width * 0.5f, height * 0.5f);
  24. OFFSET_TEMP_FLOAT[0] = width;
  25. OFFSET_TEMP_FLOAT[1] = height;
  26. OFFSET_MATRIX.mapPoints(OFFSET_TEMP_FLOAT);
  27. return (width - OFFSET_TEMP_FLOAT[0]) * (degrees > 0.0f ? 1.0f : -1.0f);
  28. }
  29. }

到此我们的源码分析为止


题外话

如果各位觉得还行的话,欢迎在github上面 star或者 fork,谢谢 ,github项目地址ViewPagerTabIndicator

转载请注明原博客地址

源码下载地址:

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注