Move a View with animation

Try the Compose way
Jetpack Compose is the recommended UI toolkit for Android. Learn how to use Animations in Compose.

Objects on screen often need to be repositioned due to user interaction or processing behind the scenes. Instead of immediately updating the object's position, which causes it to blink from one area to another, use an animation to move it from the starting position to its end position.

One way that Android lets you reposition your view objects on screen is by using ObjectAnimator. You provide the end position you want the object to settle in as well as the duration of the animation. You can also use time interpolators to control the acceleration or deceleration of the animation.

Change the view position with ObjectAnimator

The ObjectAnimator API provides a way to change the properties of a view with a specified duration. It contains static methods to create instances of ObjectAnimator depending on what type of attribute you are animating. When repositioning your views on screen, use the translationX and translationY attributes.

Here's an example of an ObjectAnimator that moves the view to a position 100 pixels from the left of the screen in 2 seconds:

Kotlin

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

Java

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

This example uses the ObjectAnimator.ofFloat() method, because the translation values have to be floats. The first parameter is the view you want to animate. The second parameter is the property you are animating. Since the view needs to move horizontally, the translationX property is used. The last parameter is the end value of the animation. In this example, the value of 100 indicates a position that many pixels from the left of the screen.

The next method specifies how long the animation takes, in milliseconds. In this example, the animation runs for 2 seconds (2000 milliseconds).

The last method causes the animation to run, which updates the view's position on screen.

For more information about using ObjectAnimator, see Animate using ObjectAnimator.

Add curved motion

While using the ObjectAnimator is convenient, by default it repositions the view along a straight line between the starting and ending points. Material design relies on curves for spatial movement of objects on the screen and the timing of an animation. Using curved motion gives your app a more material feel while making your animations more interesting.

Define your own path

The ObjectAnimator class has constructors that let you animate coordinates using two or more properties at once along with a path. For example, the following animator uses a Path object to animate the X and Y properties of a view:

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
}

Here is what the arc animation looks like:

Figure 1. A curved path animation.

An Interpolator is an implementation of an easing curve. See the Material Design documentation for more information about the concept of easing curves. An Interpolator defines how specific values in an animation are calculated as a function of time. The system provides XML resources for the three basic curves in the Material Design specification:

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

Use PathInterpolator

The PathInterpolator class is an interpolator introduced in Android 5.0 (API 21). It is based on a Bézier curve or a Path object. The Android examples in the Material Design documentation for easing use PathInterpolator.

PathInterpolator has constructors based on different types of Bézier curves. All Bézier curves have start and end points fixed at (0,0) and (1,1), respectively. The other constructor arguments depend on the type of Bézier curve being created.

For example, for a quadratic Bézier curve only the X and Y coordinates of one control point are needed:

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();
}

This produces an easing curve that starts quickly and decelerates as it approaches the end.

The cubic Bézier constructor similarly has fixed start and end points, but it requires two control points:

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();
}

This is an implementation of the Material Design emphasized decelerate easing curve.

For greater control, an arbitrary Path can be used to define the curve:

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();
}

This produces the same easing curve as the cubic Bézier example, but it uses a Path instead.

You can also define a path interpolator as an XML resource:

<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"/>

Once you create a PathInterpolator object, you can pass it to the Animator.setInterpolator() method. The Animator uses the interpolator to determine the timing or path curve when it is started.

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();