Android开发中属性动画(ObjectAnimator)中 插值器(Time Interpolator )详解
程序员文章站
2022-07-05 23:30:33
在 Android开发中,为了保持良好的交互体验,我们经常会用到动画来提升用户体验,而动画中属性动画用的最多。
虽然动画可以让界面看起来不是那么粗糙,但是很多时候仅仅只是匀速运动...
在 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
btn_green.xml
text_round.xml