Android開發中屬性動畫(ObjectAnimator)中 插值器(Time Interpolator )詳解
阿新 • • 發佈:2019-01-04
在 Android開發中,為了保持良好的互動體驗,我們經常會用到動畫來提升使用者體驗,而動畫中屬性動畫用的最多。
雖然動畫可以讓介面看起來不是那麼粗糙,但是很多時候僅僅只是勻速運動的動畫可能不足以描述一些我們想呈現給使用者的介面,比如模擬一個下落的小球,我們知道下落的小球並不是以勻速運動的,而是加速下落的,如果要實現這樣一個效果,我們可能就需要用到 Time Interpolator 。
其實 Android
已經給我們提供了若干型別的 interpolator
供我們使用,一般情況下這些已經足夠我們使用了,所以也就不需要我們自己創造了,下面我們就具體瞭解一下各個型別的 interpolator
AccelerateDecelerateInterpolator
緩慢啟動,中間過程移動非常快,緩慢結束,適用於在螢幕上啟動和結束的動畫。AccelerateInterpolator
緩慢啟動,在移動過程中慢慢加快,適用於在螢幕上啟動,螢幕外結束的動畫。AnticipateInterpolator
類似於AccelerateInterpolator
,但是有一個導致它以負值啟動的彈力,一次一個物體向下移動的動畫會先向上移動,然後再向下移動,可以理解為把一個物體放在一個彈弓上向後拉然後彈射出去。AnticipateOvershootInterpolator
AnticipateInterpolator
相同,到達終點後會繼續以這個速度繼續向原來的方向運動一段距離之後再回到終點。BounceInterpolator
類似於一個有彈性的小球掉到地上,然後又彈回來,再落下去,但是每次彈起來的高度會越來越低,直到最終靜止在地面上。CycleInterpolator
運動曲線類似於sin
函式,起始位置相當於sin
零點,終點相當於sin
的頂點。比如有一個處於中心的一個小球,你的目標是把它移到下方的一個位置,這個位置暫稱之為終點,那這個小球的運動軌跡會是 : 先向下移動到終點,然後再向上移動到初始位置,然後在向上移動 初始位置到終點 同樣的距離,然後再返回到初始位置。這是一個週期,至於動畫會執行幾個週期,這取決於你在建構函式中傳入的浮點引數,這個引數就是週期。DecelerateInterpolator
以最大速度啟動,結束時放慢速度,適用於在螢幕之外啟動,在螢幕內結束的動畫。FastOutLinearInInterpolator
在support
庫中,這個插值器使用一個查詢表來描述位移。簡單的說,它的啟動過程像AccelerateInterpolator
,結束過程像LinearInterpolator
。FastOutSlowInInterpolator
在support
庫中,這個插值器也是使用一個查詢表來描述位移。它的啟動過程像AccelerateInterpolator
,結束過程像DecelerateInterpolator
。LinearInterpolator
以一個恆定的速度變化的動畫。LinearOutSlowInInterpolator
在support
庫中,這個插值器也是使用一個查詢表來描述位移。它的啟動過程像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:推薦一個優惠券網站:優惠券領取-券券貓