要点
Interpolator — Android中的接口,将动画进度的小数值(从0.0到1.0)映射到具有修改速度的实际值。如果动画持续300毫秒,系统会为每一帧调用Interpolator,传递当前进度。Interpolator返回修改后的值 — 例如,对于AccelerateInterpolator,在50%的时间点,动画仅完成约25%的路程,模拟加速效果。
从数学上讲,Interpolator可以表示为函数f(t),其中t是归一化时间[0,1],f(t)是归一化值[0,1](对于Overshoot/Bounce可能更宽)。线性插值器返回f(t) = t — 对象以恒定速度运动。AccelerateInterpolator近似f(t) = t²,DecelerateInterpolator近似f(t) = 1 − (1 − t)²,创建平滑的起始或结束。在Android动画框架中,Interpolator同时应用于ValueAnimator、ObjectAnimator和ViewPropertyAnimator,提供了在所有层级上统一管理速度的方法。
Android提供了9种内置插值器,每种都有其数学模型。插值器的选择决定了动画的特性:物理性(Bounce)、弹性(Overshoot)或平滑性(AccelerateDecelerate)。
| 插值器 | 数学 | 场景 |
|---|---|---|
| LinearInterpolator | f(t) = t | 进度指示器,跑马灯 |
| AccelerateInterpolator | f(t) = tⁿ (n=2) | 元素飞出屏幕,从底部出现 |
| DecelerateInterpolator | f(t) = 1 − (1 − t)ⁿ | 对象下落,从顶部进入并减速 |
| AccelerateDecelerateInterpolator | 余弦近似 | 通用,元素出现/消失 |
| AnticipateInterpolator | 带后退的三次曲线 | 弹性进入 — 对象在开始前略微后退 |
| OvershootInterpolator | 带超调的三次曲线 | 操作按钮 — 略微超过目标位置 |
| AnticipateOvershootInterpolator | Anticipate + Overshoot组合 | 卡片 — 后退 + 超调并返回 |
| BounceInterpolator | 衰减弹跳 | 球,元素落到表面 |
| PathInterpolator | 三次贝塞尔(2个控制点) | 设计系统的自定义曲线 |
每个插值器在res/interpolator/中有XML声明,在android.view.animation包中有Kotlin类。AccelerateDecelerateInterpolator — 最常用的:其曲线类似于CSS中的ease-in-out缓动函数。对于使用Material Design的Android应用程序,建议对浮动操作按钮(FAB)使用OvershootInterpolator — 能在出现时创建「跳跃」效果。
PathInterpolator — 基于贝塞尔曲线的插值器,通过Path对象定义。从API 21(Android 5.0)开始可用。允许直观地设计速度曲线 — 设计师绘制曲线,开发人员通过控制点坐标将其转换为代码。仅支持三次贝塞尔曲线(两个控制点C1、C2)。
PathInterpolator曲线始终从点(0,0)开始到点(1,1)结束。控制点确定形状:(x1,y1) — 起点,(x2,y2) — 终点。x值必须在[0,1]范围内 — 这保证了时间上的单调性。y值可以超出[0,1] — 这会创建超调(overshoot)或后退(anticipate)效果。例如,标准的Material Design使用控制点(0.4,0.0,0.2,1.0)的fast-out-slow-in曲线。在IT Sectr,我们为每个设计系统构建自定义PathInterpolator — 这保证了所有屏幕上动画的一致性。
如果内置插值器不满足场景需求,Android允许通过实现TimeInterpolator接口来创建自己的插值器。唯一的方法是getInterpolation(input: Float):Float。Input — 当前动画进度(0到1);output — 修改后的值。output可以超出[0,1]范围以实现超调或弹跳效果。
典型的自定义插值器:带阻尼的弹跳效果(超出1.0并返回)、弹性效果(正弦阻尼)、阶梯插值器(离散跳跃)。自定义插值器也可以通过XML使用<interpolator>标签并指定类来定义。在Android Studio的Layout Inspector中有内置的插值器预览 — 显示所选插值器的实际曲线,方便调试。
使用对称插值器实现按钮缩放的基本动画。ValueAnimator将值从1.0更改为1.2再返回,AccelerateDecelerateInterpolator使运动变得平滑。
import android.animation.ValueAnimator
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.View
fun View.pulseAnimation() {
ValueAnimator.ofFloat(1.0f, 1.2f).apply {
duration = 300
interpolator = AccelerateDecelerateInterpolator()
repeatCount = 1
repeatMode = ValueAnimator.REVERSE
addUpdateListener { animator ->
val scale = animator.animatedValue as Float
this@pulseAnimation.scaleX = scale
this@pulseAnimation.scaleY = scale
}
start()
}
}
AccelerateDecelerateInterpolator在开始时创建平滑的增长,在结束时平滑地返回。REVERSE方法以相反方向重复动画,创建脉冲效果。这种模式用于操作按钮,将用户的注意力吸引到界面的关键元素上。
带超调效果的自定义曲线 — 对象超过目标位置10%然后返回。控制点(0.4,0.0,0.6,1.3)定义了带超调的加速进入。
import android.animation.ObjectAnimator
import android.graphics.Path
import android.view.animation.PathInterpolator
import android.view.View
fun View.slideWithOvershoot() {
val path = Path().apply {
cubicTo(0.4f, 0.0f, 0.6f, 1.3f, 1.0f, 1.0f)
}
val interpolator = PathInterpolator(path)
ObjectAnimator.ofFloat(this, "translationY", 200f, 0f).apply {
duration = 400
interpolator = interpolator
start()
}
}
PathInterpolator接受带有三次贝塞尔曲线的Path。在示例中,元素「超过」目标位置(在60%时间处y=1.3)然后返回终点。Path必须在x轴上严格单调,否则动画将反向进行。使用Android Studio中的Layout Inspector进行验证。
带有衰减弹跳效果的自定义插值器。通过带有四个阻尼周期的TimeInterpolator实现。
import android.animation.TimeInterpolator
class DampedBounceInterpolator : TimeInterpolator {
private val cycles = 4
private val damping = 0.85f
override fun getInterpolation(input: Float): Float {
val t = input * cycles
val decay = Math.pow(damping.toDouble(), cycles.toDouble()).toFloat()
val peak = t - (Math.floor(t.toDouble())).toFloat()
val bounce = Math.sin(peak * Math.PI).toFloat()
return 1f - bounce * decay * (1f - input)
}
}
自定义DampedBounceInterpolator创建4次衰减弹跳,阻尼系数为0.85。getInterpolation方法接收线性输入并返回带有「弹簧」效果的值。在IT Sectr,我们使用此插值器实现通知的出现动画 — 弹跳创造了物理感并吸引了注意力。
常见问题
AccelerateDecelerateInterpolator创建对称曲线 — 对象在开始时加速,在结束时减速。PathInterpolator允许通过带控制点的Path(三次贝塞尔)定义任意曲线。对于具有非对称行为的自定义动画(例如,快速启动 + 慢速结束),使用控制点(0.2,0.8,0.4,1.0)的PathInterpolator。
可以,实现TimeInterpolator接口并重写getInterpolation(input: Float):Float方法。Input — 0到1的小数值(动画进度),output — 实际值。例如,弹跳效果通过返回大于1或小于0的值来实现弹性行为。通过XML标签
PathInterpolator在API 21(Android 5.0 Lollipop)中添加。对于旧版本,使用AccelerateDecelerateInterpolator或自定义TimeInterpolator。PathInterpolator只支持带有两个控制点的三次贝塞尔曲线 — 直线和二次曲线可能产生不正确的插值。为了向后兼容,使用AccelerateDecelerateInterpolator作为备选方案。
Material Design 3推荐使用控制点(0.4,0.0,0.2,1.0)的fast-out-slow-in曲线用于元素出现,linear-out-slow-in(0.0,0.0,0.2,1.0)用于消失,fast-out-linear-in(0.4,0.0,1.0,1.0)用于移动。在Android中,这些曲线在Material Components库的FastOutSlowInInterpolator类中实现。
影响极小。内置插值器每帧执行一次数学运算 — 开销几乎不可察觉。带有繁重计算(三角函数、循环)的自定义插值器可能会在低性能设备上引起微卡顿。通过在构造函数中预计算值或使用带缓存的TimeInterpolator进行优化。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。