android person类_Android 阻尼动画那些事儿SpringAnimation 详解

点击上方“技术最TOP”,星标公众号

重磅干货,第一时间送达

131e2d95e90363b1a85f851633e623e2.png

文章链接:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0330/7757.html

SpringAnimation 类是最25.3.0版本才添加在支持库中的一个类,它主要是为了让实现弹性动画变得更加方便,其实facebook在很久以前的 Rebound库就实现了这样的动画,而且效果非常好,不过现在有官方支持肯定是更好了。本文先来看看SpringAnimation的基本用法,然后再将它和 Rebound做一些比较。

SpringAnimation类介绍

SpringAnimation类位于android.support.animation包之下,别和属性动画混淆了,属性动画的包是android.animation.Animator,看来以后对动画的临时增改都会放在android.support.animation里面了。跟SpringAnimation一起放出的类还有:

其中SpringAnimation类是DynamicAnimation类的子类,而DynamicAnimation的意思是符合动力学的动画,也就是物理动画。

为什么要使用SpringAnimation?

我们已经有万能的属性动画了, 使用 BounceInterpolator 或者 OvershootInterpolator作为插值器不是一样可以弹来弹去么,为什么还需要SpringAnimation呢?

主要是因为用它实现弹性动画非常简单,而且BounceInterpolator 或者 OvershootInterpolator的轨迹并不符合物理学上的弹跳效果。

SpringAnimation的基本用法

先引入必要的包:

compile 'com.android.support:support-dynamic-animation:25.3.0'

使用SpringAnimation非常简单,几行代码

SpringForce springForce = new SpringForce(0)
            .setDampingRatio(SpringForce.DAMPING_RATIO_HIGH_BOUNCY)
            .setStiffness(SpringForce.STIFFNESS_VERY_LOW);
    final SpringAnimation anim = new SpringAnimation(view ,SpringAnimation.TRANSLATION_Y).setSpring(springForce);
    anim.start();

就是这么简单。

对以上代码的解释

我们首先定义了一个用于设置弹性参数的 SpringForce 对象,其构造参数中的 0 表示被作用对象的最终位置。

setDampingRatio(float dampingRatio)方法设置弹性阻尼,dampingRatio越大,摆动次数越少,当到1的时候完全不摆动,注意它体验出来的最明显的特征是摆动次数这个概念,SpringForce类中预定义了几个dampingRatio常量:

public static final float DAMPING_RATIO_HIGH_BOUNCY = 0.2f;
     
    public static final float DAMPING_RATIO_MEDIUM_BOUNCY = 0.5f;
     
    public static final float DAMPING_RATIO_LOW_BOUNCY = 0.75f;
     
    public static final float DAMPING_RATIO_NO_BOUNCY = 1f;

setStiffness(float stiffness)方法设置弹性的生硬度,stiffness值越小,弹簧越容易摆动,摆动的时间越长,反之摆动时间越短,注意它体验出来的最明显的特征是摆动时间这个概念。SpringForce类中预定义了几个stiffness的常量:

public static final float STIFFNESS_HIGH = 10_000f;
     
    public static final float STIFFNESS_MEDIUM = 1500f;
     
    public static final float STIFFNESS_LOW = 200f;
     
    public static final float STIFFNESS_VERY_LOW = 50f;

定义好了SpringForce对象,我们就可以定义SpringAnimation了,将被作用的view和变化属性传递给SpringAnimation的构造函数,然后调用setSpring设置我们定义好了的SpringForce对象。最后调用SpringAnimationstart()方法开始动画。

前面的代码中,SpringAnimation构造方法只有两个参数:

public SpringAnimation(View v, ViewProperty property)

其实还有一个三个参数的构造方法

public SpringAnimation(View v, ViewProperty property, float finalPosition)

这个构造方法的第三个参数其实就是用于创建SpringForce对象,一般来讲使用这个构造方法的时候我们要设置阻尼和生硬度是先调用 getSpring()获得SpringForce,然后再调用setDampingRatiosetStiffness

所以前面的代码也可以这么写:

final SpringAnimation anim = new SpringAnimation(view ,SpringAnimation.TRANSLATION_Y,0);
    anim.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_HIGH_BOUNCY);
    anim.getSpring().setStiffness(SpringForce.STIFFNESS_VERY_LOW);
    anim.start();

那么问题来了,我们可以通过SpringForce设置被作用对象(一般就是一个view)的最终位置,那么怎么设置起始位置呢?默认起始位置就是view属性的当前值。如果你要设置可以调用SpringAnimation的setStartValue(float startValue)方法,比较怪异的是,起始位置不是由SpringForce决定的(而最终位置却是)。

最后值得一提的就是SpringAnimation可以作用的属性:

    TRANSLATION_X
    TRANSLATION_Y
    TRANSLATION_Z
    SCALE_X
    SCALE_Y
    ROTATION
    ROTATION_X
    ROTATION_Y
    X
    Y
    Z
    ALPHA
    SCROLL_X
    SCROLL_Y

比如我们要改变Y轴上的位置就使用

new SpringAnimation(view ,SpringAnimation.TRANSLATION_Y);

这里的SpringAnimation.TRANSLATION_Y也可以换成 DynamicAnimation.TRANSLATION_Y

小球弹跳的例子

定义布局

<?xml  version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/root_view"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffff">
     
        <Buttonandroid:id="@+id/bounce"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="跳"android:layout_marginBottom="63dp"android:layout_alignParentBottom="true"android:layout_alignParentRight="true"android:layout_alignParentEnd="true" />
     
        <ImageViewandroid:id="@+id/ball"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_above="@id/bounce"android:scaleType="centerCrop"android:layout_centerHorizontal="true"android:src="@drawable/ball" />
     
    RelativeLayout>

布局定义好了之后,我们准备使用SpringAnimation让这个小球跳起来

 import android.content.Intent;
    import android.support.animation.DynamicAnimation;
    import android.support.animation.SpringAnimation;
    import android.support.animation.SpringForce;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
     
    public class BallActivity extends AppCompatActivity {
     
        private Button buttonBounce ;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_ball);
            buttonBounce = (Button)findViewById(R.id.bounce);
            final View ball = findViewById(R.id.ball);
     
            SpringForce spring = new SpringForce(0)
                    .setDampingRatio(0.05f)
                    .setStiffness(SpringForce.STIFFNESS_VERY_LOW);
            final SpringAnimation anim = new SpringAnimation(ball ,SpringAnimation.TRANSLATION_Y).setSpring(spring);
     
            buttonBounce.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    anim.cancel();
                    anim.setStartValue(-700);
                    anim.start();
                }
             });
     
        }
    }
81c3dd5dccbb722f6584a96a64595c2a.gif

与Rebound的比较

SpringAnimation是直接作用于一个view,而Rebound是对数值区间进行采样,并不直接改变view的属性。Rebound的使用方法更类似ValueAnimator

下面是Rebound的代码示例:

// Create a system to run the physics loop for a set of springs.
    SpringSystem springSystem = SpringSystem.create();
     
    // Add a spring to the system.
    Spring spring = springSystem.createSpring();
     
    // Add a listener to observe the motion of the spring.
    spring.addListener(new SimpleSpringListener() {
     
      @Override
      public void onSpringUpdate(Spring spring) {
        // You can observe the updates in the spring
        // state by asking its current value in onSpringUpdate.
        float value = (float) spring.getCurrentValue();
        float scale = 1f - (value * 0.5f);
        myView.setScaleX(scale);
        myView.setScaleY(scale);
      }
    });
     
    // Set the spring in motion; moving from 0 to 1
    spring.setEndValue(1);

Rebound这种处理方式的好处是,如果要同时改变多个属性,会方便很多,而SpringAnimation的优势是不用关心数值上的处理,你只要告诉我最终值就行了。

为了对比Rebound和SpringAnimation的效果(流畅度),我做了一个demo,分别用Rebound和SpringAnimation实现Rebound官网上的示例项目,你可以下载下来运行,比较一下。两个例子都有滑杆控制阻尼之类的参数,我调节了多次参数,得出的结论是两者效果都差不多。

df71fc571dbd7422fc308dd099dd9a8f.png

所以你会用哪个呢?tell me。

本文的所有例子demo在这里:https://github.com/jianghejie/SpringAnimationDemo

---END---

推荐阅读:
Jetpack架构组件篇—WorkManager使用篇
阿里巴巴为什么不用 ZooKeeper 做服务发现?
【译】使用Kotlin从零开始写一个现代Android 项目-Part1
Jetpack 重磅更新!都有哪些新功能?
首款国产操作系统面世,比Windows更美观?
最流行的 RESTful API 要怎么设计?
Jetpack Compose 重磅更新!
神一样的存在,Dagger Hilt !!
四连问:API 接口应该如何设计?如何保证安全?如何签名?如何防重?
【译】使用Kotlin从零开始写一个现代Android 项目-Part1

11856caf5dc467d2b9096872dd753120.png

更文不易,点个“在看”支持一下👇
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值