专栏首页androidBlogAndroid打造不一样的新手引导页面(二)

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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/52270186

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


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

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

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

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

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

实现原理说明

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

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

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:

  • 那么该页面的position是1,A页面的position是-1,C页面的position是1.
  • 当我们从B页面滑到c页面的时候,B页面的变化是从0减少到-1,C页面的 变化是从1减少到0,A页面的变化是从从-1向负无穷变化。当我们切好滑动到一半的时候B页面的position是-0.5,c页面的position是0.5。
  • 当我们从B页面滑动到A页面的时候,B页面的变化是【0,1】,A页面的变化是【-1,0】,c页面的变化是从1向正无穷变化

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

Google的两个例子

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

ZoomOutPageTransformer

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);
        }
    }
}

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

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

if (position < -1) { // [-Infinity,-1)
    // This page is way off-screen to the left.
    page.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) {
        page.setTranslationX(horzMargin - vertMargin / 2);
    } else {
        page.setTranslationX(-horzMargin + vertMargin / 2);
    }

    // Scale the page down (between MIN_SCALE and 1)
    page.setScaleX(scaleFactor);
    page.setScaleY(scaleFactor);

    // Fade the page relative to its size.
    page.setAlpha(MIN_ALPHA +
            (scaleFactor - MIN_SCALE) /
                    (1 - MIN_SCALE) * (1 - MIN_ALPHA));

} else { // (1,+Infinity]
    // This page is way off-screen to the right.
    page.setAlpha(0);
}

DepthPageTransformer

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);
        }
    }
}

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


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

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

public class CubeOutTransformer extends BaseTransformer {

    @Override
    protected void onTransform(View view, float position) {
        view.setPivotX(position < 0f ? view.getWidth() : 0f);
        view.setPivotY(view.getHeight() * 0.5f);
        view.setRotationY(90f * position);
    }



    @Override
    public boolean isPagingEnabled() {
        return true;
    }

}

TableTransformer

public class TableTransformer extends BaseTransformer {

    private static final Matrix OFFSET_MATRIX = new Matrix();
    private static final Camera OFFSET_CAMERA = new Camera();
    private static final float[] OFFSET_TEMP_FLOAT = new float[2];
    private static final float  minScale=0.6f;

    @Override
    protected void onTransform(View view, float position) {
        final float rotation = (position < 0 ? 30f : -30f) * Math.abs(position);

        view.setTranslationX(getOffsetXForRotation(rotation, view.getWidth(), view.getHeight()));
        view.setPivotX(view.getWidth() * 0.5f);
        view.setPivotY(0);
        view.setRotationY(rotation);
        float scaleX=Math.max(1-Math.abs(position),minScale);
        view.setScaleX(scaleX);

    }

    protected static final 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);
    }
}

到此我们的源码分析为止


题外话

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

转载请注明原博客地址

源码下载地址:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 你真的了解View的坐标吗?

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

    用户2965908
  • 自定义View常用例子二(点击展开隐藏控件,九宫格图片控件)

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

    用户2965908
  • 360面试总结(Android)

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

    用户2965908
  • How many integers can you find(容斥原理) - HDU 1796

    看这题之前先复习一下容斥原理,不然肯定看不懂,呃,如果第一次接触容斥原理的题,可能弄懂了容斥原理你还是看不懂代码,是的,等会你就知道了。

    ACM算法日常
  • 代码的抽象三原则

    所谓"抽象化",就是指从具体问题中,提取出具有共性的模式,再使用通用的解决方法加以处理。

    sunsky
  • 设计师的春天:中文WebFont解决方案Font-Spider(字蛛) - 腾讯ISUX

    腾讯ISUX
  • 年终薪酬调研指南

    每年的年底HR开始进行外部的薪酬的调研,通过外部的薪酬的调研来进行公司内部的薪酬结构的调整,今天我们就来聊一聊如何进行外部的薪酬调研。

    王佩军
  • 2017互联网10大薪酬最高的职位,数据开发第二,人工智能第三

    互联网是目前最热门的行业,也是处在风口上的行业。都说互联网行业工资高,有多高呢?2017互联网职位薪酬排名显示,互联网薪酬最高的职位是管理岗,平均薪酬达2.3万...

    企鹅号小编
  • JS所有内置对象属性和方法汇总

    对象,是任何一个开发者都无法绕开和逃避的话题,她似乎有些深不可测,但如此伟大和巧妙的存在,一定值得你去摸索、发现、征服。

    前端博客 : alili.tech
  • TF-IDF应用:自动提取关键词、找相似文章、自动摘要

    这个标题看上去好像很复杂,其实我要谈的是一个很简单的问题。 有一篇很长的文章,我要用计算机提取它的关键词(Automatic Keyphrase extrac...

    机器学习AI算法工程

扫码关注云+社区

领取腾讯云代金券