SpringAnimation詳解-Android

JacQKQ 7年前發布 | 26K 次閱讀 Spring 安卓開發 Android開發 移動開發

SpringAnimation 類是最近(25.3.0版本)才添加在支持庫中的一個類,它主要是為了讓實現彈性動畫變得更加方便,其實非死book在很久以前的 Rebound 庫就實現了這樣的動畫,而且效果非常好,不過現在有官方支持肯定是更好了。本文先來看看SpringAnimation的基本用法,然后再將它和 Rebound 做一些比較。

SpringAnimation類介紹

SpringAnimation類位于android.support.animation包之下,別和屬性動畫混淆了,屬性動畫的包是android.animation.Animator,看來以后對動畫的臨時增改都會放在android.support.animation里面了。跟SpringAnimation一起放出的類還有:

DynamicAnimation <T extends  DynamicAnimation <T>> 這是物理動畫類的基類
DynamicAnimation.ViewProperty ViewProperty持有一個View的屬性。
SpringAnimation SpringAnimation是由一個 SpringForce 驅動的動畫。
SpringForce Spring Force defines the characteristics of the spring being used in the animation.

其中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對象。最后調用SpringAnimation的start()方法開始動畫。

前面的代碼中,SpringAnimation構造方法只有兩個參數:

public SpringAnimation(View v, ViewProperty property)

其實還有一個三個參數的構造方法

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

這個構造方法的第三個參數其實就是用于創建SpringForce對象,一般來講使用這個構造方法的時候我們要設置阻尼和生硬度是先調用 getSpring()獲得SpringForce,然后再調用setDampingRatio和setStiffness。

所以前面的代碼也可以這么寫:

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">

    <Button
        android: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" />

    <ImageView
        android: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讓這個小球跳起來

package com.jcodecraeer.springanimationdemo;

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

    }
}

效果如下:

與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官網上的示例項目,你可以下載下來運行,比較一下。兩個例子都有滑桿控制阻尼之類的參數,我調節了多次參數,得出的結論是兩者效果都差不多。

所以你會用哪個呢?tell me。

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

 

來自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0330/7757.html

 

 本文由用戶 JacQKQ 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!