1. 程式人生 > >Android開發中屬性動畫(ObjectAnimator)中 插值器(Time Interpolator )詳解

Android開發中屬性動畫(ObjectAnimator)中 插值器(Time Interpolator )詳解

Android開發中,為了保持良好的互動體驗,我們經常會用到動畫來提升使用者體驗,而動畫中屬性動畫用的最多。
雖然動畫可以讓介面看起來不是那麼粗糙,但是很多時候僅僅只是勻速運動的動畫可能不足以描述一些我們想呈現給使用者的介面,比如模擬一個下落的小球,我們知道下落的小球並不是以勻速運動的,而是加速下落的,如果要實現這樣一個效果,我們可能就需要用到 Time Interpolator
其實 Android 已經給我們提供了若干型別的 interpolator 供我們使用,一般情況下這些已經足夠我們使用了,所以也就不需要我們自己創造了,下面我們就具體瞭解一下各個型別的 interpolator

的使用方法和適用場景。

  • AccelerateDecelerateInterpolator 緩慢啟動,中間過程移動非常快,緩慢結束,適用於在螢幕上啟動和結束的動畫。
  • AccelerateInterpolator 緩慢啟動,在移動過程中慢慢加快,適用於在螢幕上啟動,螢幕外結束的動畫。
  • AnticipateInterpolator 類似於 AccelerateInterpolator ,但是有一個導致它以負值啟動的彈力,一次一個物體向下移動的動畫會先向上移動,然後再向下移動,可以理解為把一個物體放在一個彈弓上向後拉然後彈射出去。
  • AnticipateOvershootInterpolator
    前半部分與AnticipateInterpolator 相同,到達終點後會繼續以這個速度繼續向原來的方向運動一段距離之後再回到終點。
  • BounceInterpolator 類似於一個有彈性的小球掉到地上,然後又彈回來,再落下去,但是每次彈起來的高度會越來越低,直到最終靜止在地面上。
  • CycleInterpolator 運動曲線類似於 sin 函式,起始位置相當於 sin 零點,終點相當於 sin 的頂點。比如有一個處於中心的一個小球,你的目標是把它移到下方的一個位置,這個位置暫稱之為終點,那這個小球的運動軌跡會是 : 先向下移動到終點,然後再向上移動到初始位置,然後在向上移動 初始位置到終點 同樣的距離,然後再返回到初始位置。這是一個週期,至於動畫會執行幾個週期,這取決於你在建構函式中傳入的浮點引數,這個引數就是週期。
  • DecelerateInterpolator 以最大速度啟動,結束時放慢速度,適用於在螢幕之外啟動,在螢幕內結束的動畫。
  • FastOutLinearInInterpolatorsupport 庫中,這個插值器使用一個查詢表來描述位移。簡單的說,它的啟動過程像 AccelerateInterpolator ,結束過程像 LinearInterpolator
  • FastOutSlowInInterpolatorsupport 庫中,這個插值器也是使用一個查詢表來描述位移。它的啟動過程像 AccelerateInterpolator ,結束過程像 DecelerateInterpolator
  • LinearInterpolator 以一個恆定的速度變化的動畫。
  • LinearOutSlowInInterpolatorsupport 庫中,這個插值器也是使用一個查詢表來描述位移。它的啟動過程像 LinearInterpolator ,結束過程像 DecelerateInterpolator
  • OvershootInterpolator 類似於 AccelerateInterpolator,但是有一個是它不能立即停到終點位置的力,使它超過終點位置,然後在彈回終點,就想撞到了彈弓上。
  • PathInterpolator 這個是在 Android 5.0(API level 21) 中加入的,這個插值動畫基於你穿給它的一個路徑。X 座標表示時間,Y 座標代表返回的浮點值。如果你任意給定的 X 值只對應一個 Y 值,並且沒有間斷(即一段給定的 0~1 之間的 X 值對應一段連續的 Y 值),那麼所有種類的路徑都可以被支援。

我們來看一下使用各個 interpolator 的執行效果。

下面附上原始碼:

testActivity.class

import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.AnticipateOvershootInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.CycleInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class testActivity extends AppCompatActivity {
    ImageView testImage;
    ObjectAnimator mObjectAnimator;
    TimeInterpolator mTimeInterpolator;
    String currentInterpolator = "AccelerateDecelerateInterpolator";
    int count = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);//隱藏標題欄
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);//隱藏狀態列
        setContentView(R.layout.activity_test);

        testImage = findViewById(R.id.image_test);

        mObjectAnimator = ObjectAnimator.ofFloat(testImage,"translationY",0,600);
        mObjectAnimator.setDuration(2000);
        mTimeInterpolator = new AccelerateDecelerateInterpolator();
        mObjectAnimator.setInterpolator(mTimeInterpolator);


        Button startButton = findViewById(R.id.testButton);
        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mObjectAnimator.setInterpolator(mTimeInterpolator);
                mObjectAnimator.start();
            }
        });
        final TextView stringAcc = findViewById(R.id.stringAcc);
        stringAcc.setText("AccelerateDecelerateInterpolator");
        Button next =findViewById(R.id.nextButton);
        next.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                count ++;
                if(count>11){
                    count = 0;
                }
                switch(count){
                    case 0:mTimeInterpolator = new AccelerateDecelerateInterpolator();
                        currentInterpolator = "AccelerateDecelerateInterpolator";break;
                    case 1:mTimeInterpolator = new AccelerateInterpolator();
                        currentInterpolator = "AccelerateInterpolator";break;
                    case 2:mTimeInterpolator = new AnticipateInterpolator();
                        currentInterpolator = "AnticipateInterpolator";break;
                    case 3:mTimeInterpolator = new AnticipateOvershootInterpolator();
                        currentInterpolator = "AnticipateOvershootInterpolator";break;
                    case 4:mTimeInterpolator = new BounceInterpolator();
                        currentInterpolator = "BounceInterpolator";break;
                    case 5:mTimeInterpolator = new CycleInterpolator(1.0f);
                        mObjectAnimator = ObjectAnimator.ofFloat(testImage,"translationX",0,250);
                        mObjectAnimator.setDuration(2000);
                        currentInterpolator = "CycleInterpolator";break;
                    case 6:mTimeInterpolator = new DecelerateInterpolator();
                        mObjectAnimator = ObjectAnimator.ofFloat(testImage,"translationY",0,600);
                        mObjectAnimator.setDuration(2000);
                        currentInterpolator = "DecelerateInterpolator";break;
                    case 7:mTimeInterpolator = new FastOutLinearInInterpolator();
                        currentInterpolator = "FastOutLinearInInterpolator";break;
                    case 8:mTimeInterpolator = new FastOutSlowInInterpolator();
                        currentInterpolator = "FastOutSlowInInterpolator";break;
                    case 9:mTimeInterpolator = new LinearInterpolator();
                        currentInterpolator = "LinearInterpolator";break;
                    case 10:mTimeInterpolator = new LinearOutSlowInInterpolator();
                        currentInterpolator = "LinearOutSlowInInterpolator";break;
                    case 11:mTimeInterpolator = new OvershootInterpolator();
                        currentInterpolator = "OvershootInterpolator";break;


                }
                stringAcc.setText(currentInterpolator);
            }
        });
    }
    
}

activity_test.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.tobetheonlyone.testActivity"
    android:background="#ede7e7">
    <ImageView
        android:id="@+id/image_test"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentTop="true"
        android:layout_marginTop="30dp"
        android:layout_centerHorizontal="true"
        android:background="@drawable/text_round"/>
    <Button
        android:id="@+id/testButton"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="20dp"
        android:background="@drawable/btn_green"
        android:layout_marginStart="10dp"
        android:layout_marginEnd="10dp"
        android:text="開始"/>
    <Button
        android:id="@+id/nextButton"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_above="@+id/testButton"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="10dp"
        android:layout_marginStart="10dp"
        android:layout_marginEnd="10dp"
        android:background="@drawable/btn_green"
        android:text="下一個"/>
    <TextView
        android:id="@+id/stringAcc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/nextButton"
        android:layout_marginBottom="10dp"
        android:layout_centerHorizontal="true"
        android:textSize="25sp"/>

</RelativeLayout>

btn_green.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true" >
        <shape >
            <solid
                android:color="#07e18c" />
            <stroke
                android:width="1.0dp"
                android:color="#07e18c" />
            <corners
                android:radius="3dp" />
        </shape>
    </item>
    <item>
        <shape >
            <stroke
                android:width="2.0dp"
                android:color="#06f799" />
            <corners
                android:radius="3dp" />
        </shape>
    </item>

text_round.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item>
        <shape android:shape="oval">

            <size android:width="100dp" android:height="100dp"/>
            <solid android:color="#29694d"/>
        </shape>
    </item>
</selector>

PS:推薦一個優惠券網站:優惠券領取-券券貓