使用动画移动 View

尝试 Compose 方式
Jetpack Compose 是 Android 推荐的界面工具包。了解如何在 Compose 中使用动画。

屏幕上的对象通常需要因用户互动或后台处理而重新定位。与其立即更新对象位置(这会导致其从一个区域闪烁到另一个区域),不如使用动画将其从起始位置移动到结束位置。

Android 在屏幕上重新定位 View 对象的一种方法是使用 ObjectAnimator。您可以提供希望对象停留的最终位置以及动画持续时间。您还可以使用时间插值器来控制动画的加速或减速。

使用 ObjectAnimator 更改 View 位置

ObjectAnimator API 提供了一种在指定持续时间内更改 View 属性的方法。它包含用于创建 ObjectAnimator 实例的静态方法,具体取决于您动画化的属性类型。在屏幕上重新定位 View 时,请使用 translationXtranslationY 属性。

以下是 ObjectAnimator 的一个示例,它在 2 秒内将 View 移动到屏幕左侧 100 像素的位置

Kotlin

ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    duration = 2000
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setDuration(2000);
animation.start();

此示例使用 ObjectAnimator.ofFloat() 方法,因为平移值必须是浮点数。第一个参数是您要动画化的 View。第二个参数是您要动画化的属性。由于 View 需要水平移动,因此使用 translationX 属性。最后一个参数是动画的结束值。在此示例中,值 100 表示距离屏幕左侧 100 像素的位置。

下一个方法指定动画持续的时间(以毫秒为单位)。在此示例中,动画运行 2 秒(2000 毫秒)。

最后一个方法使动画运行,从而更新 View 在屏幕上的位置。

有关使用 ObjectAnimator 的更多信息,请参阅使用 ObjectAnimator 进行动画化

添加曲线运动

虽然使用 ObjectAnimator 很方便,但默认情况下,它会沿着起始点和结束点之间的直线重新定位 View。Material Design 依赖曲线来控制屏幕上对象的空间移动和动画的时间。使用曲线运动可以让您的应用更具 Material 设计感,同时让您的动画更有趣。

定义自己的路径

ObjectAnimator 类有构造函数,可让您使用两个或更多属性以及路径同时动画化坐标。例如,以下动画器使用 Path 对象来动画化 View 的 X 和 Y 属性

Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    val path = Path().apply {
        arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true)
    }
    val animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path).apply {
        duration = 2000
        start()
    }
} else {
    // Create animator without using curved path
}

Java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true);
  ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
  animator.setDuration(2000);
  animator.start();
} else {
  // Create animator without using curved path
}

以下是弧形动画的效果图

图 1. 曲线路径动画。

Interpolator 是缓动曲线的一种实现。有关缓动曲线概念的更多信息,请参阅Material Design 文档Interpolator 定义如何将动画中的特定值计算为时间的函数。系统为 Material Design 规范中的三种基本曲线提供了 XML 资源

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

使用 PathInterpolator

PathInterpolator 类是 Android 5.0 (API 21) 中引入的一种插值器。它基于贝塞尔曲线Path 对象。Material Design 缓动文档中的 Android 示例使用了 PathInterpolator

PathInterpolator 包含基于不同类型贝塞尔曲线的构造函数。所有贝塞尔曲线的起始点固定为 (0,0),结束点固定为 (1,1)。其他构造函数参数取决于正在创建的贝塞尔曲线的类型。

例如,对于二次贝塞尔曲线,只需要一个控制点的 X 和 Y 坐标

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.67f, 0.33f)
} else {
    LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.67f, 0.33f);
} else {
  myInterpolator = new LinearInterpolator();
}

这会产生一个快速启动并在接近结束时减速的缓动曲线。

三次贝塞尔构造函数同样具有固定的起始点和结束点,但它需要两个控制点

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f)
} else {
    LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f);
} else {
  myInterpolator = new LinearInterpolator();
}

这是 Material Design 强调减速缓动曲线的一种实现。

为了获得更好的控制,可以使用任意 Path 来定义曲线

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  val path = Path().apply {
    moveTo(0.0f, 0.0f)
    cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f)
  }
  PathInterpolator(path)
} else {
  LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.moveTo(0.0f, 0.0f);
  path.cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f);
  myInterpolator = new PathInterpolator(path);
} else {
  myInterpolator = new LinearInterpolator();
}

这产生的缓动曲线与三次贝塞尔曲线示例相同,但它使用 Path 代替。

您还可以将路径插值器定义为 XML 资源

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.5"
    android:controlY1="0.7"
    android:controlX2="0.1f"
    android:controlY2="1.0f"/>

创建 PathInterpolator 对象后,可以将其传递给 Animator.setInterpolator() 方法。启动时,Animator 会使用该插值器来确定时间或路径曲线。

Kotlin

val animation = ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    interpolator = myInterpolator
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setInterpolator(myInterpolator);
animation.start();