Android 中基于物理特性的动画简介

Android 中基于物理特性的动画简介

AceycleeAceyclee
简评:基于物理特性的动画依赖于物理学定律,这能在动画中表现出高度的现实感。

什么是基于物理的动画?

  • 这是一种遵循物理学定律的动画形式
  • 能够依据加速度和速度去计算和更新每一帧的动画数值
  • 当受力平衡时,动画为处于恒定运动或静止状态

和普通动画有什么不一样?

  • 自然:动画模仿实时的动作,看起来更自然
  • 反应:当目标值发生变化时,动画保持动量(速度)并以更平滑的运动结束
  • 较少的视觉干扰:动画看起来更流畅,反应灵敏度也更高

考虑在动画期间目标值需要改变的情况。

左侧使用 ObjectAnimator 构建的动画以及右侧基于物理 API 的动画差异

使用 Animator 构建的动画是一种恒定速率的形式,并且具有固定的持续时间。为了适应目标值的变化,您需要在目标值更改时取消动画,将当前值的动画重新配置为新的起始值,并添加新的目标值。

在视觉上,这个过程中在动画里创建了一个突然停止,并且之后又突然运动的一个不连贯的动作。

而使用基于物理的动画 API 构建的动画则自然得多。目标值的变化导致力的变化,新的运动适用于现有的速度,而且是连续过渡到新的目标,这样的过程显示的动画效果更符合人们的日常认知。

添加基于物理的动画支持库

为了开始使用基于物理的动画,将这个库添加到 build.gradle 文件中:

compile "com.android.support:support-dynamic-animation:25.4.0"

该库提供了两个 Animation 类:SpringAnimation 和 FlingAnimation

弹簧动画(Spring Animation)

弹簧大家都知道,拉伸时会缩回去,压缩时又会弹回来。

应用到 App 中就是这样一个效果:

Spring translate animation applied on an ImageView

现在,让我们先了解一下 Spring 的属性,然后再看看如何实现:

弹力(Spring Force)

SpringForce 类允许开发者通过改变弹簧的阻尼比,刚度和静止位置来控制弹簧的性能。一旦动画开始,弹簧力就会更新动画值和每帧的速度。动画继续,直到控件受力平衡。

阻尼比(Damping ratio):受力平衡前的振荡次数。您可以通过它来改变弹簧的弹性,阻尼比为零将无限振荡,高阻尼比将很快停止动画。

阻尼比可以从高弹性到无弹性常数。

DAMPING_RATIO_HIGH_BOUNCY = 0.2f; // more oscillations
DAMPING_RATIO_NO_BOUNCY = 1f; // very few oscillations

刚度(Stiffness):振荡速度。这将控制物体快速恢复到其静止位置。

STIFFNESS_HIGH = 10_000f; // would quickly come back to its resting position
STIFFNESS_VERY_LOW = 50f; // would slowly come back, like a loose suspension

平衡位置(Resting position):弹力达到平衡的位置。

为了实现上面所示的动画,我们创建一个 SpringAnimation 类的实例:

SpringAnimation springX = new SpringAnimation(mViewToBeAnimated,
        new FloatPropertyCompat<View>("translationX") {

            @Override
            public float getValue(View view) {
                return view.getTranslationX();
            }

            @Override
            public void setValue(View view, float value) {
                view.setTranslationX(value);
            }
        });

SpringForce springForceX = new SpringForce(0f);
springForceX.setStiffness(SpringForce.STIFFNESS_MEDIUM);
springForceX.setDampingRatio(SpringForce.DAMPING_RATIO_HIGH_BOUNCY);
springX.setSpring(springForceX);
springX.start();

对于构造函数 SpringAnimation,我们提供我们想要动画化的视图,以及我们想要动画化的属性。在这种情况下 imageView,我们想要动画的对象是 TRANSLATION_X,我们想要动画的属性是左右颠倒视图。

我们创建一个 springForce 实例,并将弹簧的最终静止位置的值设置为零,以便视图能回到起始点。

最后弹簧动画效果就大功告成了!开不开心!

抛掷动画(Fling Animation)

现在弹出一个控件之后,让我们看看如何做出像现实中物体上抛的效果。

上抛运动大家也都很熟悉,在现实世界中向上扔一个物体,它会有一个初速度,然后它在这个速度的惯性下继续运动,直到引力的作用下逐渐停止。

为了模拟上抛运动向上阶段的过程,我们将使用 FlingAnimation 库中可用的类。

先看个例子,在横轴和纵轴上移动一个物体,它的效果:

Fling translate animation applied on an ImageView

为了接收 callbacks,当动作开始时,我们需要设置一个姿势监听器。一旦检测到这个回来的姿势,我们会收到 onFling 回调,同时在坐标轴上有一个 downEvent,一个 upEvent 和一个速度(以每秒移动的单位像素为单位)。

设置 StartVelocity

默认情况下,起始速度设置为零像素 / 秒。在这种情况下,它会在下一帧中停止动画。因此,您必须定义起始速度,以确保动画不会马上结束。

设置最小值和最大值

要在特定范围内为属性值设置动画时,请设置最小和最大动画值。一旦 Fling 动画达到其最小 动画值或最大动画值,它将立即结束。

设置反作用力

需要设置反作用力来控制动画变慢时的速度现在我们准备创建一个 Fling 动画:

private GestureDetector.OnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {

        ...
        @Override
        public boolean onFling(MotionEvent downEvent, MotionEvent moveEvent, float velocityX, float velocityY) {

            //Fling Right/Left
            FlingAnimation flingX = new FlingAnimation(mViewTobeFlung, DynamicAnimation.TRANSLATION_X);
            flingX.setStartVelocity(velocityX)
              .setMinValue(MIN_TRANSLATION) // minimum translationX property
              .setMaxValue(maxTranslationX)  // maximum translationX property
              .setFriction(FRICTION)
              .start();

            return true;
        }
}

对于 FlingAnimation 构造函数,我们提供我们想要的动画对象和要动画化的属性。在这种情况下 imageView,我们想要动画的对象是 TRANSLATION_X,最后,在 onFling() 方法中启动 fling 动画。

结论

使用新的基于物理的动画系统,我们不需要为创建基于物理的动画提供持续时间或开始和结束值。Google 已经开放接口让开发人员能轻松创建酷炫动画,只需几行代码即可模拟物理定律。

原文链接:Introduction to Physics-based animations in Android

推荐阅读:手把手教你实现一个低配版象棋 AlphaGo
「真诚赞赏,手留余香」
还没有人赞赏,快来当第一个赞赏的人吧!
文章被以下专栏收录
12 条评论
推荐阅读