【Animations】使用弹簧物理学动画运动(8)

原文

概要


基于物理的运动是由武力驱动的。春天的力量是指导互动和运动的一种力量。弹簧力具有以下特性:阻尼和刚度。在基于弹簧的动画中,值和速度是基于每个帧上应用的弹簧力来计算的。

如果您希望应用程序的动画仅在一个方向上减速,请考虑使用基于摩擦的 投射动画 。

春天动画的生命周期


在基于弹簧的动画中,SpringForce 课程可让您自定义弹簧刚度,阻尼比和最终位置。只要动画开始,弹簧力就会更新每帧的动画值和速度。动画一直持续到弹簧力达到平衡。

例如,如果您在屏幕上拖动一个应用程序图标,然后通过将图标从手指上抬起来释放该图标,该图标就会被一种看不见的但熟悉的力量拖回原来的位置。

图1展示了一个类似的弹簧效果。圆圈中间的加号(+)表示通过触摸手势施加的力。

图1. Spring发布效果

构建一个春天的动画


为您的应用程序构建弹簧动画的一般步骤如下所示:

  • 添加支持库 您必须将支持库添加到项目才能使用弹簧动画类。
  • 创建弹簧动画: 主要步骤是创建SpringAnimation类的实例 并设置动作行为参数。
  • (可选)注册侦听器: 注册侦听器以监视动画生命周期更改和动画值更新。

注意:只有当您需要对动画值更改进行每帧更新时,才应该注册更新侦听器。更新侦听器可防止动画在单独的线程上运行。

  • (可选)删除侦听器: 删除不再使用的侦听器。
  • (可选)设置开始值: 自定义动画开始值。
  • (可选)设置值范围: 设置动画值范围以将值限制在最小和最大范围内。
  • (可选)设置开始速度: 设置动画的开始速度。
  • (可选)设置弹簧属性:设置弹簧 的阻尼比和刚度。
  • (可选)创建自定义弹簧: 创建自定义弹簧,以防您不打算使用默认弹簧或想在整个动画中使用通用弹簧。
  • 开始动画: 开始弹簧动画。
  • (可选)取消动画: 如果用户突然退出应用或视图变为不可见,则取消动画。

以下各节将详细讨论构建弹簧动画的一般步骤。

添加支持库


  dependencies {
      implementation 'com.android.support:support-dynamic-animation:27.1.1'
  }

创建一个春天的动画

在SpringAnimation类,您可以为对象创建一个春天的动画。要创建一个弹簧动画,需要创建一个SpringAnimation 类的实例并提供一个对象,一个对象的属性,您想要动画,以及一个可选的最终弹簧位置,您希望动画休息。
注意:在创建弹簧动画时,弹簧的最终位置是可选的。但是,它必须在开始动画之前定义。

final View img = findViewById(R.id.imageView);
// Setting up a spring animation to animate the view’s translationY property with the final
// spring position at 0.
final SpringAnimation springAnim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0);

通过改变视图对象中的实际属性,基于弹簧的动画可以在屏幕上激活视图。系统中提供以下视图:

  • ALPHA:表示视图上的alpha透明度。该值默认为1(不透明),值为0表示完全透明(不可见)。
  • TRANSLATION_X,, TRANSLATION_Y和 TRANSLATION_Z:这些属性控制视图所在的位置,以其左侧坐标,顶部坐标和高程(由布局容器设置)作为增量进行定位。
    • TRANSLATION_X 描述左边的坐标。
    • TRANSLATION_Y 描述顶部坐标。
    • TRANSLATION_Z 描述视图相对于其高程的深度。
  • ROTATION,, ROTATION_X和 ROTATION_Y:这些属性控制rotation围绕枢轴点的2D(属性)和3D旋转。
  • SCROLL_X和 SCROLL_Y:这些属性指示左侧源和上边缘的滚动偏移量(以像素为单位)。它也表明了页面滚动的位置。
  • SCALE_X和 SCALE_Y:这些属性控制围绕其中心点的视图的2D缩放比例。
  • X,, Y和 Z:这些是用于描述视图在其容器中的最终位置的基本实用属性。
    • X是左值和的总和TRANSLATION_X。
    • Y是最高值和的总和TRANSLATION_Y。
    • Z是高程值和的总和TRANSLATION_Z。

注册监听者

本DynamicAnimation类提供了两个听众:OnAnimationUpdateListener 和OnAnimationEndListener。这些侦听器会侦听动画中的更新,例如动画值发生变化并且动画结束时。

OnAnimationUpdateListener

如果要为多个视图设置动画效果以创建链接动画,则可以设置OnAnimationUpdateListener 每次当前视图属性发生更改时接收回调。回调通知其他视图根据当前视图属性中发生的更改更新其弹簧位置。要注册侦听器,请执行以下步骤

  1. 调用addUpdateListener() 方法并将侦听器附加到动画。

注意:您需要在动画开始之前注册更新侦听器。但是,只有在动画值更改需要每帧更新时,才应该注册更新侦听器。更新侦听器可防止动画在单独的线程上运行

  1. 重写该onAnimationUpdate() 方法以通知调用者有关当前对象的更改。以下示例代码说明了整体使用情况 OnAnimationUpdateListener。
// Creating two views to demonstrate the registration of the update listener.
final View view1 = findViewById(R.id.view1);
final View view2 = findViewById(R.id.view2);

// Setting up a spring animation to animate the view1 and view2 translationX and translationY properties
final SpringAnimation anim1X = new SpringAnimation(view1,
        DynamicAnimation.TRANSLATION_X);
final SpringAnimation anim1Y = new SpringAnimation(view1,
    DynamicAnimation.TRANSLATION_Y);
final SpringAnimation anim2X = new SpringAnimation(view2,
        DynamicAnimation.TRANSLATION_X);
final SpringAnimation anim2Y = new SpringAnimation(view2,
        DynamicAnimation.TRANSLATION_Y);

// Registering the update listener
anim1X.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() {

// Overriding the method to notify view2 about the change in the view1’s property.
    @Override
    public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value,
                                  float velocity) {
        anim2X.animateToFinalPosition(value);
    }
});

anim1Y.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() {

  @Override
    public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value,
                                  float velocity) {
        anim2Y.animateToFinalPosition(value);
    }
});

OnAnimationEndListener

OnAnimationEndListener 通知动画结束。每当动画达到平衡或取消时,您都可以设置侦听器来接收回调。要注册侦听器,请执行以下步骤:

  1. 调用addEndListener() 方法并将侦听器附加到动画。
  2. 重写onAnimationEnd() 方法以在动画达到平衡或取消时接收通知。

删除监听器

要分别停止接收动画更新回调和动画结束回调,调用removeUpdateListener() 和removeEndListener() 方法

设置动画开始值

要设置动画的起始值,请调用该 setStartValue() 方法并传递动画的起始值。如果您未设置起始值,则动画会将对象属性的当前值用作起始值

设置动画值范围

如果要将属性值限制在一定范围内,可以设置最小动画值和最大动画值。如果您为具有固有范围的属性(例如alpha(从0到1))制作动画,则它还有助于控制范围。

  • 要设置最小值,请调用 setMinValue() 方法并传递该属性的最小值。
  • 要设置最大值,请调用setMaxValue() 方法并传递属性的最大值。

两种方法都会返回正在设置值的动画。
注意:如果您已设置起始值并定义了动画值范围,请确保起始值在最小值和最大值范围内。

设置开始速度

开始速度定义了动画属性在动画开始时的变化速度。默认启动速度设置为每秒零像素。您可以使用触摸手势的速度或使用固定值作为起始速度来设置速度。如果您选择提供固定值,我们建议以每秒dp为单位定义值,然后将其转换为每秒像素。以每秒dp定义值允许速度独立于密度和形状因子。有关将值转换为每秒像素数的更多信息,请参阅 将每秒转换为每秒像素数 部分。

要设置速度,请调用该 setStartVelocity() 方法并以每秒像素为单位传递速度。该方法返回设置速度的弹力对象。

注意:使用 GestureDetector.OnGestureListener或 VelocityTracker类方法检索并计算触摸手势的速度。

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);
…
// Compute velocity in the unit pixel/second
            vt.computeCurrentVelocity(1000);
            float velocity = vt.getYVelocity();
anim.setStartVelocity(velocity);

将每秒转换为每秒像素数

弹簧的速度必须以每秒像素为单位。如果您选择提供固定值作为速度的开始,请提供每秒dp的值,然后将其转换为每秒像素数。对于转换,请使用该类中的 applyDimension() 方法TypedValue。请参阅以下示例代码:

float pixelPerSecond = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, getResources().getDisplayMetrics());

设置弹簧属性

的SpringForce类定义了吸气和setter方法对于每个弹簧特性,如阻尼比和刚度。要设置弹簧属性,重要的是检索弹簧力对象或创建一个可以在其上设置属性的自定义弹簧力。有关创建自定义弹簧力的更多信息,请参阅 创建自定义弹簧力 部分。
提示:在使用setter方法时,您可以创建一个方法链,因为所有setter方法都会返回弹簧力对象。

阻尼比

阻尼比描述了弹簧振动的逐渐减小。通过使用阻尼比,您可以定义振荡从一次反弹到下一次反射衰减的速度。有四种不同的方法可以防止春季潮湿:

  • 当阻尼比大于1时发生过阻尼。它可以让物体快速返回休息位置。
  • 当阻尼比等于1时发生临界阻尼。它可以让对象在最短的时间内返回休息位置。
  • 当阻尼比小于1时发生欠阻尼。它让物体通过静止位置多次超调,然后逐渐达到静止位置。
  • 当阻尼比等于零时发生未阻尼。它让对象永远振荡。

要将阻尼比添加到弹簧,请执行以下步骤:

  1. 调用该getSpring() 方法来检索弹簧以添加阻尼比。
  2. 调用该setDampingRatio() 方法并传递想要添加到弹簧的阻尼比。该方法返回设置阻尼比的弹簧力对象。

注意:阻尼比必须是非负数。如果将阻尼比设置为零,则弹簧永远不会到达静止位置。换句话说,它永远在摇摆。

系统中有以下阻尼比常数:

  • DAMPING_RATIO_HIGH_BOUNCY
  • DAMPING_RATIO_MEDIUM_BOUNCY
  • DAMPING_RATIO_LOW_BOUNCY
  • DAMPING_RATIO_NO_BOUNCY


图2:高反弹

图3:中等反弹

图4:低反弹

图5:没有反弹

默认的阻尼比设置为DAMPING_RATIO_MEDIUM_BOUNCY。

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);
…
//Setting the damping ratio to create a low bouncing effect.
anim.getSpring().setDampingRatio(DAMPING_RATIO_LOW_BOUNCY);
…

刚性

刚度定义了测量弹簧强度的弹簧常数。当弹簧不在静止位置时,坚硬的弹簧对连接的物体施加更大的力。要为弹簧添加刚度,请执行以下步骤:

  1. 调用该getSpring() 方法来检索弹簧以添加刚度。
  2. 调用该setStiffness() 方法并传递要添加到弹簧的刚度值。该方法返回设置刚度的弹簧力对象。

注意:刚度必须是正数。

系统中有以下刚度常数:

  • STIFFNESS_HIGH
  • STIFFNESS_MEDIUM
  • STIFFNESS_LOW
  • STIFFNESS_VERY_LOW


图6:高刚度

图7:中等硬度

图8:低刚度

图9:非常低的刚度

默认刚度设置为STIFFNESS_MEDIUM。

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);
…
//Setting the spring with a low stiffness.
anim.getSpring().setStiffness(STIFFNESS_LOW);
…

创建一个自定义弹簧力量

您可以创建自定义弹簧力来替代使用默认弹簧力。自定义弹簧力可让您在多个弹簧动画中共享相同的弹力实例。一旦创建了弹力,就可以设置阻尼比和刚度等属性。

  1. 创建一个SpringForce对象。

    SpringForce force = new SpringForce();
  2. 通过调用相应的方法来分配属性。你也可以创建一个方法链。

    force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW);

  3. 调用该setSpring() 方法将弹簧设置为动画。

    setSpring(force);

开始动画

有两种方法可以启动弹簧动画:通过调用 start()或调用 animateToFinalPosition() 方法。这两种方法都需要在主线程中调用。

animateToFinalPosition() 方法执行两项任务:

  • 设置弹簧的最终位置。
  • 如果尚未开始,则开始动画。

由于该方法更新弹簧的最终位置,并在需要时启动动画,所以您可以随时调用此方法来更改动画的过程。例如,在链式弹簧动画中,一个视图的动画取决于另一个视图。对于这样的动画,使用该animateToFinalPosition() 方法更为方便 。通过在链式弹簧动画中使用此方法,您无需担心下一个要更新的动画是否正在运行。

图10展示了一个链式弹簧动画,其中一个视图的动画依赖于另一个视图。

图10.链式弹簧演示
要使用该animateToFinalPosition() 方法,请调用该 animateToFinalPosition() 方法并传递弹簧的静止位置。您也可以通过调用该setFinalPosition() 方法来设置弹簧的静止位置 。

该start()方法不会立即将属性值设置为起始值。属性值在每个动画脉冲中发生变化,这发生在绘制过程之前。因此,这些更改会反映在下一个框架中,就像这些值立即设置一样。

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);
…
//Starting the animation
anim.start();
…

取消动画

您可以取消或跳至动画的结尾。在需要取消或跳过amiation结束时的理想情况是,当用户交互要求动画立即终止时。这主要是当用户突然退出应用程序或视图变得不可见时。

有两种方法可以用来终止动画。该cancel()方法终止动画的值。而 canSkipToEnd()方法则将动画跳到最终值,然后终止它。

在您终止动画之前,首先检查弹簧的状态非常重要。如果状态不受阻塞,动画将无法到达休息位置。要检查弹簧的状态,请调用该 canSkipToEnd()方法。如果弹簧被阻尼,则方法返回true,否则 false。

一旦你知道弹簧的状态,您可以通过使用终止动画 skipToEnd()的方法或 cancel()method.The cancel()方法 必须只能在主线程中调用。

注意:通常,该 skipToEnd()方法会导致视觉跳跃。

Lastest Update:2018.05.08

联系我

QQ:94297366
微信打赏:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ

公众号推荐:

转载于:https://blog.51cto.com/4789781/2120984

你可能感兴趣的:(【Animations】使用弹簧物理学动画运动(8))