使用ViewPager动画来做出不一样的引导页

就算Google从很早开始就自带了设置引导页动画的接口,但是就我目前看来市面上使用引导页动画的还是很少的,也不知道是为什么,一想到Material Design的使用率也这么少表示很心塞。

首先来看看市面上千篇一律的引导页效果,诺:

很单调对不对,你们没看吐我都看吐了,再看一份加了引导页动画效果的:

有没有瞬间耳目一新的感觉,下面就谈谈如何做出这样的引导页动画。



其实从Android 3.0也就是API 11开始Android就自带了一个PageTransformer接口用来实现ViewPager动画效果并为之加入了setPageTransformer方法来自定义我们自己的动画效果,用的时候很简单:

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

这里setPageTransformer传入了两个参数,第一个布尔型参数表示的意思就是在两个页面切换产生动画效果时候是否要反转一下让下一个页面在上一个页面底下,因为ViewPager默认下一个页面是绘制在上一个页面的上面,这里一般传入true,第二次参数才是重点,这里实现了PageTransformer接口,然后我们所有需要的动画效果都在transformPage这个接口方法里面实现,现在我们来看看这个方法。

我们发现transformPage方法也有两个参数,第一个参数就表示当前显示在屏幕上的Activity或者Fragment,这个不管,后一个参数是重点,这个position并不是我们引导页页面的position,下面借用一张图来说明这个position参数:

图片出处

谷歌官方对这个参数的解释是,这个参数表明了一个给定的页面相对于屏幕中心的位置,并且这个参数随着我们的滑动会动态的变化,最重要的一点是这个position参数是相对于我们的屏幕左边缘来说的,如果当前的页面刚好占满了整个屏幕,就如上图所示的1界面,那么这个页面的position参数就是0,如果一个页面刚从屏幕右边缘划出来,可以理解为上图中页面1和页面2的交界线刚冒头的情况,那么这个页面的position值就是1,如果某个时刻我们把页面1向左滑动一半,导致屏幕中央既有一半页面1显示又有一半页面2显示的时候,这时候页面1的position值就是-0.5,页面2的position值就是0.5,都是相对于左边缘来说的,而且左边缘的值固定是0,就是下面这种情况:

那么知道这个值有什么用呢,其实多亏了这个值我们才能做出更好的动画效果,要知道这个值是动态变化的,有了一个动态变化的值就可以做出动态变化的效果,我们可以看看谷歌是怎么用它的:

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

这份代码的实际效果如下:

可以看到很明显的缩放以及透明度的变换,我们看看代码是怎么利用这个position参数的:

 if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);

首先这里判断如果position参数是负无穷到-1的时候,也就是此时这个page划出了屏幕左边缘之外不可见得情况,直接设置为透明的

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

接下里判断如果这个页面的position处于-1到1之间,也就是最极端的情况是这个页面即将向左边滑出屏幕之外,或者说这个页面还在屏幕右边缘即将滑入我们的视线,这时就用到了我们的position参数,这里谷歌把它当成了一个缩放系数来用;

float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));

这里1 - Math.abs(position)) 的值在0~1之间,并且代码判断了MIN_SCALE和1 - Math.abs(position)) 的大小并取其中的最大值,MIN_SCALE是最上面定义的最小缩放系数,可以看到这一行代码得出来的缩放系数是处于MIN_SCALE和1之间的,然后下面的代码就是根据position位置参数的变化来进行page的水平移动效果,其实ViewPager提供了相当多的方法共给我们去操作,诸如:setScale设置缩放啦,setRotation设置旋转效果,还有这里的setTranslationX设置水平移动效果等等,结合position这个动态变化的参数可以做出很多意想不到的动画,比如下面这个旋转动画:

代码如下:

public class  RotateDownPageTransformer implements ViewPager.PageTransformer
{

    private static final float ROT_MAX = 20.0f;
    private float mRot;

    public void transformPage(View view, float position)
    {

        Log.e("TAG", view + " , " + position + "");

        if (position < -1)
        { // [-Infinity,-1)
            // This page is way off-screen to the left.
            ViewHelper.setRotation(view, 0);

        } else if (position <= 1) // a页滑动至b页 ; a页从 0.0 ~ -1 ;b页从1 ~ 0.0
        { // [-1,1]
            // Modify the default slide transition to shrink the page as well
            if (position < 0)
            {

                mRot = (ROT_MAX * position);
                ViewHelper.setPivotX(view, view.getMeasuredWidth() * 0.5f);
                ViewHelper.setPivotY(view, view.getMeasuredHeight());
                ViewHelper.setRotation(view, mRot);
            } else
            {

                mRot = (ROT_MAX * position);
                ViewHelper.setPivotX(view, view.getMeasuredWidth() * 0.5f);
                ViewHelper.setPivotY(view, view.getMeasuredHeight());
                ViewHelper.setRotation(view, mRot);
            }

            // Scale the page down (between MIN_SCALE and 1)

            // Fade the page relative to its size.

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

注意:这里的ViewHelper类需要引用nineoldandroids第三方动画库来实现,具体的东西我都打包好了在最下面有下载链接,需要的自行取用。



更酷炫的效果

其实除了对position这个参数进行处理,我们还可以对view进行动画处理,前面提到transformPage这个接口方法第一个参数view就是当前可见的Activity或Fragment,那么我们还可以对这个Activity或Fragment内部的元素进行处理来达到视察动画的效果,一个很好地例子:

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 <= 1) { // [-1,1]

        mBlur.setTranslationX((float) (-(1 - position) * 0.5 * pageWidth));
        mBlurLabel.setTranslationX((float) (-(1 - position) * 0.5 * pageWidth));

        mDim.setTranslationX((float) (-(1 - position) * pageWidth));
        mDimLabel.setTranslationX((float) (-(1 - position) * pageWidth));

        mCheck.setTranslationX((float) (-(1 - position) * 1.5 * pageWidth));
        mDoneButton.setTranslationX((float) (-(1 - position) * 1.7 * pageWidth));
        // The 0.5, 1.5, 1.7 values you see here are what makes the view move in a different speed.
        // The bigger the number, the faster the view will translate.
        // The result float is preceded by a minus because the views travel in the opposite direction of the movement.

        mFirstColor.setTranslationX((position) * (pageWidth / 4));

        mSecondColor.setTranslationX((position) * (pageWidth / 1));

        mTint.setTranslationX((position) * (pageWidth / 2));

        mDesaturate.setTranslationX((position) * (pageWidth / 1));
        // This is another way to do it

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

工程地址

最后,附上整个项目的地址:项目地址

有任何问题可以留言探讨

时间: 2024-10-29 19:07:05

使用ViewPager动画来做出不一样的引导页的相关文章

ViewPager动画之三个item的实现

很多项目中都会有分页切换的部分,而这个需求大家大多会使用ViewPager去实现,ViewPager是V4包里的一个官方控件,帮我们处理好了页面切换和页面预加载等逻辑,使用起来简单方便,并且给我们提供了一个默认的切换动画,尽管看起来不怎么华丽: 然后公司的UI设计师看到后就说了,这动画看起来实在是平淡如水呀,得加点情怀进去,然后给了个如下的样式: Page页不是一成不变的滑入滑出,而是缩放着滑动,这该如何下手呢,突然间灵光闪现:监听ViewPager的滑动切换事件,使用OnPageChangeL

用ViewPager为你的APP引导页添加视差滚动(Parallax Scrolling)效果

什么是视差滚动 视差滚动效果是怎样的 如何实现视差滚动效果 1 通过使用ViewPager实现页面的左右滑动 2 ViewPager有办法实现ParallaxScrolling吗 3 ViewPagerPageTransformer如何使用 由视差滚动效果引起的思考 以上仅是个人在开发中收集的经验欢迎大家拍砖 1. 什么是视差滚动? Parallax Scrolling(视差滚动),是一种常见的动画效果.视差一词来源于天文学,但在日常生活中也有它的身影.在疾驰的动车上看风景时,会发现越是离得近的

ViewPager动画详解

GitHub:lightSky 微博:    light_sky, 即时分享最新技术,欢迎关注 前言 前两天看到鲍永章分享的Great animations with PageTransformer以及农民伯伯分享的Create ViewPager transitions 文章,都是通过ViewPager来实现酷炫的动画,而现在的App中ViewPager的动画使用也非常的广泛.正好最近一直研究动画,那么就趁热打铁,分析一下相关的开源库吧.本篇文章介绍的ViewPager动画,可以分为两类,第一

android:ViewPager动画总结

设置动画的方案: 我们可以使用ViewPager的setPageTransformer方法,为ViewPager设置动画.以下是几种常见动画的演示及效果: 1.CubeInTransformer 2.CubeOutTransformer 2 3.FlipHorizontalTransformer 4.RotateUpTransformer 5.ZoomOutSlideTransformer 6.TabletTransformer 更多ViewPager的动画Demo请参见源代码: https:/

Android基础控件——ViewPager实现带有动画的引导页

好了,又到我们学习基础控件的时候了,其实引导页很简单,就是五张图片而已 传统的ViewPager实现引导页和ListView是一样道理的,只是把ListView的Item换成图片,把BaseAdapter换成PagerAdapter,我们先来看下传统引导页的效果图 既然用到的是ViewPager,那么xml文件就必须要有ViewPager,细心的你,可能会发现最后一页还有个按钮的出现,没错,xml文件中也要有个按钮 开头也说了,Viewpager其实就和ListView一样的,需要一个Adapt

Android 1分钟教你打造酷炫的引导页(实现ViewPager淡入淡出切换)

纯手工自制的Android引导页,实现了Viewpager切换的淡入淡出(页面不移动!)切换以及文字动画. 下面是效果演示: 实现思路+心路历程...: 其实别的都还蛮简单的,就是这个ViewPager的淡入淡出切换动画比较棘手,以前都没有做过,然后去网上找了好久好久. 其中碰到各种坑无数,大概90%的人是引的 JazzyViewPager的包然后就balabala说自己实现了种种功能,真是醉了.... 结论是国内根本找不到这个效果的实现嘛.... 然后 在Github下了JazzyViewPa

android仿网易云音乐引导页、仿书旗小说Flutter版、ViewPager切换、爆炸菜单、风扇叶片效果等源码

Android精选源码 复现网易云音乐引导页效果 高仿书旗小说 Flutter版,支持iOS.Android Android Srt和Ass字幕解析器 Material Design ViewPager切换变色美观效果 卡证识别 相机样式 Android炫酷爆炸效果的菜单源码 Android简洁优雅可点击的toast控件,仿手机百度 Android实现水平列表,其中的项目像风扇叶片一样移动效果 让你的RecyclerView秀出传送带效果,支持横向和纵向两种选... 一种流式布局的效果,很像我们

ViewPager实现引导页

1. 要使用ViewPager,必须要创建 PagerAdapter. 这里创建一个 ViewPagerAdapter来继承PagerAdapter public class ViewPagerAdapter extends PagerAdapter{ private List<View> views; // 我们引导页的list private Context context; // 上下文 public ViewPagerAdapter(List<View> views, Co

Android用户引导页实现,圆点实现动画效果

当前市面上比较流行的应用,用户引导页已经是一个必不可缺的功能点了,简单的介绍下应用的基础功能或者版本升级功能点介绍. 那么常用的用户引导页是如何实现的呢?这篇文章就说说我个人用到的,并且觉得使用不错的效果. 1.首先定义布局文件guide_layout.xml文件,主要使用ViewPager做页面显示,使用一个圆点布局显示圆点,圆点根据图片数目动态添加. guide_layout.xml文件的代码如下: <?xml version="1.0" encoding="utf