It’s hard to imagine the mobile experience without animated elements.
They’re fun, beautiful and
hold a power of persuasion that static UI elements only wish they could have.
Building animations that make on-screen objects seem alive might seem like it could be as complex as aerospace engineering. Fear not though, Android has quite a few tools to help you create animations with relative ease. :]
You’ll learn to get comfortable with some essential animation tools in this tutorial as you work through launching Doge on a rocket into space (maybe even to the moon) and hopefully get it back safely on the ground :]
By creating these Doge animations, you’ll learn how to:
First, download the Rocket Launch Starter. Import it into Android Studio then run it on your device. You’ll find everything you need to get going quickly.
Your device will display a list of all the animations you’ll implement.
Click any item on the list.
You should see two static images: Doge and the rocket, and Doge is ready to take a ride. For now, all the screens are the same and none are yet animated.
Imagine that you need to animate a rocket launch from the bottom edge to the top edge of the screen and that the rocket should make it exactly in 50 ms.
Here’s a plotted graph that shows how the rocket’s position changes over time:
The animation above appears to be smooth and continuous. However, smartphones are digital and work with discrete values. Time does not flow continuously for them; it advances by tiny steps.
Animation consists of many still images, also known as frames, that are displayed one by one over a specified time period. The concept today is the same as it was for the first cartoons, but the rendering is a little different.
Elapsed time between frames is named frame refresh delay — it’s 10 ms by default for property animations.
Here’s where animation is different than it was in the early days of film: when you know the rocket moves at a constant speed, you can calculate the position of the rocket at any given time.
You see six animation frames shown below. Notice that:
TL/DR: When drawing a given frame, you calculate the rocket’s position based on the duration and frame refresh rate.
Fortunately, you don’t have to do all the calculations manually, because
To set up an animation, you just specify start and end values of the property being animated, as well as the duration. Additionally, you need to add a listener to call to set a new position for your rocket for every frame.
Android’s animation framework makes use of time interpolators.
Have a look again at the graph of position changes over time in the simplest case — a Linear Interpolator:
Here is how this
Depending on the time, the rocket position changes at a constant speed or linearly.
Animations can also have non-linear interpolators. One such example is the
It squares the input value, making the rocket start slowly and accelerate quickly — just like a real rocket does!
That’s pretty much all the theory you need to know to get started, so now it’s time for…
Open activity_base_animation.xml file in the res/layout folder.
In the root, you’ll find a
Open BaseAnimationActivity.java and have a look inside. At the top are
Take a look at
Here’s what you’ve got going on in here:
Open LaunchRocketValueAnimatorAnimationActivity.java, and add the following code to the body of
That was fun, right? :] Don’t worry about Doge getting left behind — he’ll catch his rocketship to the moon a bit later.
Can you spot the difference?
The above code is identical to
Build, run and select Accelerate a rocket in the list. Tap on the new screen to see how your rocket behaves.
Again, we see that poor Doge doesn’t catch the rocket to the moon…poor fella. Hang in there, buddy!
Since you used
You can tell
Unlike
Go to LaunchRocketObjectAnimatorAnimationActivity.java class and enter the following code:
Here’s what you’re doing:
The rocket behaves the same as it did with
Open ColorAnimationActivity.java and put this code into
In the code above, you:
That’s amazing! Hey, you’re getting the hang of this pretty quickly. That’s a buttery-smooth background color change :]
It’s time to send Doge to the moon! :]
Then you can call the following methods on that builder, all which have the
Open LaunchAndSpinAnimatorSetAnimatorActivity.java in your editor, and put the following code into
Here’s what you’re doing in this block:
Doge defies the laws of physics with this one.
There’s a nifty tool to simplify animating several properties of the same object. The tool is called…
Open LaunchAndSpinViewPropertyAnimatorAnimationActivity.java and add the following call to
In here,
Build and run, select Launch and spin (ViewPropertyAnimator), and you’ll see the same animation as in the previous section.
Compare your code for this section to the
Test it out by opening FlyWithDogeAnimationActivity.java and putting the following code in
In the above code you just created three animators:
Run the app and select Don’t leave Doge behind (Animating two objects). You know what to do now. To the moon!
You don’t get to observe it, but know that the rocket stops and stays off screen when the animation ends. If you don’t plan to land it or finish the activity, you could remove this particular view to conserve resources.
The structure of the code above, with the exception of the listener
part, should look the same as the previous section. Here’s what you’re
doing in there:
In Android, you can use the following methods to adjust an animation:
In here, you:
You should see your rocket jumping like a grasshopper! Take that, Elon Musk. :]
By defining animations in XML, you’re allowing reuse of animations throughout your code base.
Defining animations in XML bears some resemblance to composing view layouts.
If don’t have an animator folder under src/main/res, right-click on the res folder and select New then Android resource directory.
On the next screen, select the resource type animator.
Go to res/animator folder and right-click it to select New, then Android resource file.
Enter the filename jump_and_blink. Keep pre-selected root element as Source set.
In an open editor, you should see this:
The following XML tags are available to you:
Replace the contents of jump_and_blink.xml with the following code:
Here you declare a root element,
Take a look at the following attributes of
Go to XmlAnimationActivity.java and add the following code to
In the above code, you’re doing just a few things:
You should see Doge jumping, disappearing and then returning back to the ground safely :]
During this tutorial you:
If you’re hungry for more, check out the available time interpolators in Android’s documentation (see Known Indirect Subclasses). If you’re not happy with either of them, you can create your own. You can also set
Android has other animations systems like View animations and Drawable Animations. You can also make use of Canvas and OpenGL ES APIs to create animations. Stay tuned :]
I hope you enjoyed the Introduction to Android Animations tutorial. Chime in with your questions, ideas and feedback in the forums below!
hold a power of persuasion that static UI elements only wish they could have.
Building animations that make on-screen objects seem alive might seem like it could be as complex as aerospace engineering. Fear not though, Android has quite a few tools to help you create animations with relative ease. :]
You’ll learn to get comfortable with some essential animation tools in this tutorial as you work through launching Doge on a rocket into space (maybe even to the moon) and hopefully get it back safely on the ground :]
By creating these Doge animations, you’ll learn how to:
- Create property animations — the most useful and simple Android animations
- Move and fade Android Views
- Combine animations in a sequence or start them simultaneously
- Repeat and reverse animations
- Adjust the animations’ timing
- Become a bit of a rocket scientist. :]
Prerequisites: This Android tutorial is all about animation,
so you need basic knowledge of Android programming and familiarity with
Java, Android Studio and XML layouts.
If you’re completely new to Android, you might want to first check out our Android Tutorial for Beginners: Part 1.
Many animation. Such code. Fast rocket.If you’re completely new to Android, you might want to first check out our Android Tutorial for Beginners: Part 1.
Getting Started
Animations are such a fun topic to explore! The best way to master building animations is by getting your hands dirty in code :]First, download the Rocket Launch Starter. Import it into Android Studio then run it on your device. You’ll find everything you need to get going quickly.
Your device will display a list of all the animations you’ll implement.
Click any item on the list.
You should see two static images: Doge and the rocket, and Doge is ready to take a ride. For now, all the screens are the same and none are yet animated.
How do Property Animations Work?
Before you work with the first animation, walk down theory road a bit so you’re clear on the logic behind the magic. :]Imagine that you need to animate a rocket launch from the bottom edge to the top edge of the screen and that the rocket should make it exactly in 50 ms.
Here’s a plotted graph that shows how the rocket’s position changes over time:
The animation above appears to be smooth and continuous. However, smartphones are digital and work with discrete values. Time does not flow continuously for them; it advances by tiny steps.
Animation consists of many still images, also known as frames, that are displayed one by one over a specified time period. The concept today is the same as it was for the first cartoons, but the rendering is a little different.
Elapsed time between frames is named frame refresh delay — it’s 10 ms by default for property animations.
Here’s where animation is different than it was in the early days of film: when you know the rocket moves at a constant speed, you can calculate the position of the rocket at any given time.
You see six animation frames shown below. Notice that:
- In the beginning of the animation, the rocket is at the bottom edge of the screen.
- The rocket’s position moves upward by the same fraction of its path with every frame.
- By the end of the animation, the rocket is at the top edge of the screen.
TL/DR: When drawing a given frame, you calculate the rocket’s position based on the duration and frame refresh rate.
Fortunately, you don’t have to do all the calculations manually, because
ValueAnimator
is happy to do it for you. To set up an animation, you just specify start and end values of the property being animated, as well as the duration. Additionally, you need to add a listener to call to set a new position for your rocket for every frame.
Time Interpolators
You probably noticed that your rocket moves with the same constant speed during the entire animation — not terribly realistic. Material design encourages you to create vivid animations that catch the user’s attention while behaving in a more natural way.Android’s animation framework makes use of time interpolators.
ValueAnimator
incorporates a time interpolator – it has an object that implements TimeInterpolator
interface. Time interpolators determine how the animated value changes over time. Have a look again at the graph of position changes over time in the simplest case — a Linear Interpolator:
Here is how this
LinearInterpolator
responds to time change. Depending on the time, the rocket position changes at a constant speed or linearly.
Animations can also have non-linear interpolators. One such example is the
AccelerateInterpolator
, which looks much more interesting.It squares the input value, making the rocket start slowly and accelerate quickly — just like a real rocket does!
That’s pretty much all the theory you need to know to get started, so now it’s time for…
Your First Animation
Take some time to familiarize yourself with the project before you move on. The packagecom.raywenderlich.rocketlaunch.animationactivities
contains BaseAnimationActivity and all other activities that extend this class.Open activity_base_animation.xml file in the res/layout folder.
In the root, you’ll find a
FrameLayout
that contains two instances of ImageView
with images; one has rocket.png and the other has doge.png. Both have android:layout_gravity
set to bottom|center_horizontal
to force the images to show up at the center-bottom of the screen.
Note: You’ll do a lot of file navigation in this tutorial.
Use these handy shortcuts in Android Studio to move between things
easily:
-
Navigate to any file with command + O on Mac / Ctrl + N on Linux and Windows
-
Navigate to a Java class with command + shift + O on Mac / Ctrl + Shift + N on Linux and Windows
BaseAnimationActivity
is a super class of all other animation activities in this app.Open BaseAnimationActivity.java and have a look inside. At the top are
View
member variables that are accessible from all animation activities:mRocket
is the view with the image of the rocketmDoge
is the view that contains the Doge imagemFrameLayout
is the FrameLayout that contains bothmRocket
andmDoge
mScreenHeight
will equal the screen height for the sake of convenience
mRocket
and mDoge
are both a type of ImageView
, but you declare each as a View
since property animations work with all Android Views.Take a look at
onCreate()
to observe the code:// 1 super.onCreate(savedInstanceState); // 2 setContentView(R.layout.activity_base_animation); mRocket = findViewById(R.id.rocket); mDoge = findViewById(R.id.doge); mFrameLayout = findViewById(R.id.container); // 3 mFrameLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 4 onStartAnimation(); } }); |
- Call
onCreate()
on the superclass. - Apply XML layout and bind
FrameLayout
,mRocket
andmDoge
to their corresponding views - Set
onClickListener
onFrameLayout
. - Call
onStartAnimation()
whenever the user taps the screen. This is an abstract method defined by each of the activities that extendBaseAnimationActivity
.
Launch the Rocket
Doge isn’t going anywhere unless you initiate the rocket launch, and it’s the best animation to start with because it’s pretty easy. Who’d have thought that rocket science is so simple?Open LaunchRocketValueAnimatorAnimationActivity.java, and add the following code to the body of
onStartAnimation()
://1 ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, -mScreenHeight); //2 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //3 float value = (float) animation.getAnimatedValue(); //4 mRocket.setTranslationY(value); } }); //5 valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.setDuration(DEFAULT_ANIMATION_DURATION); //6 valueAnimator.start(); |
- Create an instance of
ValueAnimator
by calling the static methodofFloat
. It accepts the floating point numbers that’ll apply to the specified property of the animated object over time. In this case, the values start at0
and end with-mScreenHeight
. Android starts screen coordinates at the top-left corner, so the rocket’s Y translation changes from 0 to the negative of the screen height — it moves bottom to top. - Call
addUpdateListener()
and pass in a listener.ValueAnimator
calls this listener with every update to the animated value — remember the default delay of 10 ms. - Get the current value from the animator and cast it to float; current value type is
float
because you created theValueAnimator
withofFloat
. - Change the rocket’s position by using the
setTranslationY().
- Set up the animator’s duration and interpolator.
- Start the animation.
That was fun, right? :] Don’t worry about Doge getting left behind — he’ll catch his rocketship to the moon a bit later.
Put a Spin on It
How about giving the rocket a little spin action? Open RotateRocketAnimationActivity.java and add the following toonStartAnimation
:// 1 ValueAnimator animator = ValueAnimator.ofFloat(0, 360); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); // 2 mRocket.setRotation(value); } }); animator.setInterpolator(new LinearInterpolator()); animator.setDuration(DEFAULT_ANIMATION_DURATION); animator.start(); |
- Change the animator values to go from
0
to360
because you want the rocket to make a full turn. Note that you could create a U-turn effect with0
to180
. - Instead of
setTranslationY
, you callsetRotation
because that’s what needs to change.
Accelerate the Launch
Open AccelerateRocketAnimationActivity.java and add the following code to your old friendonStartAnimation()
:// 1 ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, -mScreenHeight); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); mRocket.setTranslationY(value); } }); // 2 - Here set your favorite interpolator valueAnimator.setInterpolator(new AccelerateInterpolator(1.5f)); valueAnimator.setDuration(DEFAULT_ANIMATION_DURATION); // 3 valueAnimator.start(); |
onStartAnimation()
in LaunchRocketValueAnimationActivity.java except for one line: the interpolator used for the setInterpolator()
. Build, run and select Accelerate a rocket in the list. Tap on the new screen to see how your rocket behaves.
Again, we see that poor Doge doesn’t catch the rocket to the moon…poor fella. Hang in there, buddy!
Since you used
AccelerateInterpolator
, you should see
you rocket accelerating after liftoff. Feel free to play around with
interpolators if you’d like. I’ll sit here and wait. I promise :]Which Properties Can You Animate?
Until now, you’ve only animated position and rotation forView
, but ValueAnimator
doesn’t care what you do with the value that it supplies.You can tell
ValueAnimator
to animate the value using any of the following types:float
if you createValueAnimator
instance withofFloat
int
if you do it withofInt
ofObject
is for the cases whenfloat
orint
is not enough — it’s often used to animate colors
View
. Some examples are:setScaleX(float)
andsetScaleY(float)
– these allow you to scale the view by x-axis or y-axis independently, or you can call both with the same value to animate the view’s size.setTranslationX(float)
andsetTranslationY(float)
– these allow you to change the view’s on-screen position.setAlpha(float)
– animate view’s transparency;0
stands for completely transparent and1
for completely opaque.setRotation(float)
– rotates the view on screen; the argument is in degrees, so360
means a full clockwise turn. You may specify negative values as well, for instance,-90
means a counterclockwise quarter-turn.setRotationX(float)
andsetRotationY(float)
– the same assetRotation
but along the x-axis and y-axis. These allow you to rotate in 3D.setBackgroundColor(int)
– lets you set a color. The integer argument must specify a color as Android constantsColor.YELLOW
,Color.BLUE
do.
ObjectAnimator
MeetObjectAnimator
, a subclass of ValueAnimator
. If you only need to animate a single property of a single object, ObjectAnimator
may just be your new best friend. Unlike
ValueAnimator
, where you must set a listener and do something with a value, ObjectAnimator
can handle those bits for you almost automagically. :]Go to LaunchRocketObjectAnimatorAnimationActivity.java class and enter the following code:
// 1 ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mRocket, "translationY", 0, -mScreenHeight); // 2 objectAnimator.setDuration(DEFAULT_ANIMATION_DURATION); objectAnimator.start(); |
- Creating an instance of
ObjectAnimator
(like you did withValueAnimator
) except that the former takes two more parameters:mRocket
is the object to animate- The object must have a setter method of the form
set"propertyName"()
, and the property you want to change is“translationY”
. You’re able to do this becausemRocket
is an object of classView
, which has an accessible setter withsetTranslationY()
.
- You set the duration for the animation and start it.
The rocket behaves the same as it did with
ValueAnimator
, but with less coding. :]
Note: There’s a limitation to
Consider your use cases and the amount of coding required when you decide to use
ObjectAnimator
— it can’t animate two objects simultaneously. To work around it, you create two instances of ObjectAnimator
.Consider your use cases and the amount of coding required when you decide to use
ObjectAnimator
or ValueAnimator
.Animating Color
Speaking of use cases, there’s animating colors to consider. NeitherofFloat()
nor ofInt()
can construct your animator and get good results with colors. You’re better off using ArgbEvaluator
.Open ColorAnimationActivity.java and put this code into
onStartAnimation()
://1 ObjectAnimator objectAnimator = ObjectAnimator.ofObject(mFrameLayout, "backgroundColor", new ArgbEvaluator(), ContextCompat.getColor(this, R.color.background_from), ContextCompat.getColor(this, R.color.background_to)); // 2 objectAnimator.setRepeatCount(1); objectAnimator.setRepeatMode(ValueAnimator.REVERSE); // 3 objectAnimator.setDuration(DEFAULT_ANIMATION_DURATION); objectAnimator.start(); |
- Call
ObjectAnimator.ofObject
and give it the following arguments:mFrameLayout
— the object with the property to be animated"backgroundColor"
— the property you want to animatenew ArgbEvaluator()
— an additional argument that specifies how to interpolate between two different ARGB (alpha, red, green, blue) color values- Start and end color values — you make use of
ComtextCompat.getColor()
to get the color resource id.
- Set the number of times the animation will repeat with
setRepeatCount()
. Then you usesetRepeatMode()
to define what the animation does when it reaches the end. More on this soon. - Set duration and start the animation.
That’s amazing! Hey, you’re getting the hang of this pretty quickly. That’s a buttery-smooth background color change :]
Combining Animations
Animating a view is pretty awesome, but you’ve only changed one property and one object at a time. Animations need not be so restrictive.It’s time to send Doge to the moon! :]
AnimatorSet
allows you to play several animations together or in sequence. You pass your first animator to play()
, which accepts an Animator
object as an argument, and it returns a builder. Then you can call the following methods on that builder, all which have the
Animator
object as an argument:with()
— to play theAnimator
passed as the argument simultaneously with the first one you specified inplay()
before()
— to play it beforeafter()
— to play it after
Open LaunchAndSpinAnimatorSetAnimatorActivity.java in your editor, and put the following code into
onStartAnimation()
:// 1 ValueAnimator positionAnimator = ValueAnimator.ofFloat(0, -mScreenHeight); // 2 positionAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); mRocket.setTranslationY(value); } }); // 3 ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(mRocket, "rotation", 0, 180f); // 4 AnimatorSet animatorSet = new AnimatorSet(); // 5 animatorSet.play(positionAnimator).with(rotationAnimator); // 6 animatorSet.setDuration(DEFAULT_ANIMATION_DURATION); animatorSet.start(); |
- Create a new
ValueAnimator
. - Attach an
AnimatorUpdateListener
to the ValueAnimator that updates the rocket’s position. - Create an
ObjectAnimator
, a second animator that updates the rocket’s rotation. - Create a new instance of
AnimatorSet
. - Specify that you’d like to execute
positionAnimator
together withrotationAnimator
. - Just as with a typical animator, you set a duration and call
start()
.
Doge defies the laws of physics with this one.
There’s a nifty tool to simplify animating several properties of the same object. The tool is called…
ViewPropertyAnimator
One of the greatest things about animation code that usesViewPropertyAnimator
is that it’s easy to write and read — you’ll see.Open LaunchAndSpinViewPropertyAnimatorAnimationActivity.java and add the following call to
onStartAnimation
:mRocket.animate().translationY(-mScreenHeight) .rotationBy(360f) .setDuration(DEFAULT_ANIMATION_DURATION) .start(); |
animate()
returns an instance of ViewPropertyAnimator
so you can chain the calls. Build and run, select Launch and spin (ViewPropertyAnimator), and you’ll see the same animation as in the previous section.
Compare your code for this section to the
AnimatorSet
code snippet that you implemented in the previous section:ValueAnimator positionAnimator = ValueAnimator.ofFloat(0, -mScreenHeight); positionAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); mRocket.setTranslationY(value); } }); ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(mRocket, "rotation", 0, 360f); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(positionAnimator).with(rotationAnimator); animatorSet.setDuration(DEFAULT_ANIMATION_DURATION); animatorSet.start(); |
ViewPropertyAnimator
may provide better performance for
multiple simultaneous animations. It optimizes invalidated calls, so
they only take place once for several properties — in contrast to each
animated property causing its own invalidation independently.Animating the Same Property of Two Objects
A nice feature ofValueAnimator
is that you can reuse its animated value and apply it to as many objects as you like.Test it out by opening FlyWithDogeAnimationActivity.java and putting the following code in
onStartAnimation()
://1 ValueAnimator positionAnimator = ValueAnimator.ofFloat(0, -mScreenHeight); positionAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); // You can use value to set properties of many objects mRocket.setTranslationY(value); mDoge.setTranslationY(value); } }); //2 ValueAnimator rotationAnimator = ValueAnimator.ofFloat(0, 360); rotationAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); mDoge.setRotation(value); } }); //3 AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(positionAnimator).with(rotationAnimator); animatorSet.setDuration(DEFAULT_ANIMATION_DURATION); animatorSet.start(); |
positionAnimator
— for changing positions of bothmRocket
andmDoge
rotationAnimator
— for rotating DogeanimatorSet
— to combine the first two animators
Run the app and select Don’t leave Doge behind (Animating two objects). You know what to do now. To the moon!
Animation Listeners
Animation typically implies that a certain action has occurred or will take place. Typically, whatever happens usually comes at the end of your fancy animation.You don’t get to observe it, but know that the rocket stops and stays off screen when the animation ends. If you don’t plan to land it or finish the activity, you could remove this particular view to conserve resources.
AnimatorListener
— receives a notification from the animator when the following events occur:onAnimationStart()
— called when the animation startsonAnimationEnd()
— called when the animation endsonAnimationRepeat()
— called if the animation repeatsonAnimationCancel()
— called if the animation is canceled
onStartAnimation()
://1 ValueAnimator animator = ValueAnimator.ofFloat(0, -mScreenHeight); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); mRocket.setTranslationY(value); mDoge.setTranslationY(value); } }); // 2 animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { // 3 Toast.makeText(WithListenerAnimationActivity.this, "Doge took off", Toast.LENGTH_SHORT) .show(); } @Override public void onAnimationEnd(Animator animation) { // 4 Toast.makeText(WithListenerAnimationActivity.this, "Doge is on the moon", Toast.LENGTH_SHORT) .show(); finish(); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); // 5 animator.setDuration(5000L); animator.start(); |
- Create and set up an animator. You use
ValueAnimator
to change the position of two objects simultaneously — you can’t do the same thing with a singleObjectAnimator
. - Add the
AnimatorListener
. - Show a toast message when the animation starts
- And another toast when it ends
- Start the animation as usual
Note: You also can add a listener to
Alternatively, you can set start and end actions by calling
ViewPropertyAnimator
by adding a setListener
to a call chain before calling start()
:
mRocket.animate().setListener(new AnimatorListener() { // Your action }) |
withStartAction(Runnable)
and withEndAction(Runnable)
. It’s the equivalent to an AnimatorListener
with these actions.
Animation Options
Animations are not one-trick ponies that simply stop and go. They can loop, reverse, run for a specific duration, etc.In Android, you can use the following methods to adjust an animation:
setRepeatCount
— specifies the number of times the animation should repeat after the initial run.setRepeatMode
— defines what this animation should do when it reaches the endsetDuration
— specifies the animation’s total duration
onStartAnimation()
.// 1 ValueAnimator animator = ValueAnimator.ofFloat(0, -mScreenHeight); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); mRocket.setTranslationY(value); mDoge.setTranslationY(value); } }); // 2 animator.setRepeatMode(ValueAnimator.REVERSE); // 3 animator.setRepeatCount(3); // 4 animator.setDuration(500L); animator.start(); |
- Create an animator, as usual
- You can set the
repeatMode
to either of the following:RESTART
— restarts the animation from the beginning.REVERSE
— reverses the animation’s direction with every iteration.
REVERSE
because you want the rocket to take off and then go back to the same position where it started. Just like SpaceX! :] - …Except you’ll do it twice.
- Set a duration and start the animation, as usual.
Note: So why does the third section specify the repeat count
at three? Each up-and-down motion consumes two repetitions, so you need
three to bring Doge back to earth twice: one to land the first time,
and two to launch and land again. How many times would you like to see
Doge bounce? Play around with it!
Run the app. Select Fly there and back (Animation options) in the list. A new screen is opened. Tap on the screen.You should see your rocket jumping like a grasshopper! Take that, Elon Musk. :]
Declaring Animations in XML
You’ve made it to the best part of this tutorial. In this final section, you’ll learn how to declare once and use everywhere — yes, that’s right, you’ll be able to reuse your animations with impunity.By defining animations in XML, you’re allowing reuse of animations throughout your code base.
Defining animations in XML bears some resemblance to composing view layouts.
If don’t have an animator folder under src/main/res, right-click on the res folder and select New then Android resource directory.
On the next screen, select the resource type animator.
Go to res/animator folder and right-click it to select New, then Android resource file.
Enter the filename jump_and_blink. Keep pre-selected root element as Source set.
In an open editor, you should see this:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> </set> |
set
— the same asAnimatorSet
animator
— the same asValueAnimator
objectAnimator
— you guessed correctly; it stands forObjectAnimator
AnimatorSet
in XML, you nest the ValueAnimator
and ObjectAnimator
objects inside it, similar to how you nest View
objects inside ViewGroup
objects (RelativeLayout
, LinearLayout
, etc.) in layout XML files.Replace the contents of jump_and_blink.xml with the following code:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <objectAnimator android:propertyName="alpha" android:duration="1000" android:repeatCount="1" android:repeatMode="reverse" android:interpolator="@android:interpolator/linear" android:valueFrom="1.0" android:valueTo="0.0" android:valueType="floatType"/> <objectAnimator android:propertyName="translationY" android:duration="1000" android:repeatCount="1" android:repeatMode="reverse" android:interpolator="@android:interpolator/bounce" android:valueFrom="0" android:valueTo="-500" android:valueType="floatType"/> </set> |
set
tag. Its ordering
attribute can be either together
or sequential
. It’s together
by default, but you may prefer to specify it for clarity. The set
tag has two child XML tags, each of which is an objectAnimator
. Take a look at the following attributes of
objectAnimator
:android:valueFrom
andandroid:valueTo
— specify start and end values like you did when you created an instance ofObjectAnimator
android:valueType
— value type; eitherfloatType
orintType
android:propertyName
— the property you want to animate without theset
partandroid:duration
— duration of the animationandroid:repeatCount
— the same as withsetRepeatCount
android:repeatMode
— the same as withsetRepeatMode
android:interpolator
— specify interpolator; it usually starts with@android:interpolator/
. Start typing this and Android Studio will show all available interpolators under autocomplete options- You can’t specify your target object here, but you can do it later in Java
objectAnimator
to the AnimatorSet
, and they will play together. Now, it’s time to use them. Go to XmlAnimationActivity.java and add the following code to
onStartAnimation()
:// 1 AnimatorSet rocketAnimatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.jump_and_blink); // 2 rocketAnimatorSet.setTarget(mRocket); // 3 AnimatorSet dogeAnimatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.jump_and_blink); // 4 dogeAnimatorSet.setTarget(mDoge); // 5 AnimatorSet bothAnimatorSet = new AnimatorSet(); bothAnimatorSet.playTogether(rocketAnimatorSet, dogeAnimatorSet); // 6 bothAnimatorSet.setDuration(DEFAULT_ANIMATION_DURATION); bothAnimatorSet.start(); |
- First, you load
AnimatorSet
fromR.animator.jump_and_blink
file, just like you normally would to inflate a view layout - Then you set
mRocket
as the target for just-loaded animator - Load the animator from the same file once again
- Rinse and repeat for
mDoge
object - Now you create a third
AnimatorSet
and set it up to play the first two simultaneously - Set the duration for the root animator and start
- Whew! Rest just a little bit :]
You should see Doge jumping, disappearing and then returning back to the ground safely :]
Where To Go From Here
You can grab the final project here.During this tutorial you:
- Created and used property animations with
ValueAnimator
andObjectAnimator
- Set up time interpolator of your choice for your animation
- Animated position, rotation and color for
View
- Combined animations together
- Used the spectacular
ViewPropertyAnimator
with the help ofanimate()
- Repeated your animation
- Defined the animation in XML for reuse across the project
If you’re hungry for more, check out the available time interpolators in Android’s documentation (see Known Indirect Subclasses). If you’re not happy with either of them, you can create your own. You can also set
Keyframe
s for your animation to make them very sophisticated.Android has other animations systems like View animations and Drawable Animations. You can also make use of Canvas and OpenGL ES APIs to create animations. Stay tuned :]
I hope you enjoyed the Introduction to Android Animations tutorial. Chime in with your questions, ideas and feedback in the forums below!
0 comments:
Post a Comment
Note: only a member of this blog may post a comment.