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