In today’s post I will be talking about controlling animation flow. Using the Animator
API you can start, stop and cancel animations. A little reported addition in the Kitkat API level 19 allows you to also pause and resume animations. In this post I will take you through the animation flow controls and some methods that let you inspect the status of the animation.
Animation Flow
In the previous tutorials we have already encountered the Animator.start
method multiple times. This method is used to start an animation from the beginning. The method is only one of the set of methods that control the animation flow. The complete set of methods is shown below.
Animator.start() // start the animation from the beginning Animator.end() // end the animation Animator.cancel() // cancel the animation Animator.pause() // added in API 19; pause the animation Animator.resume() // added in API 19; resume a paused animation
As already stated, the start
method starts the animation from the beginning. If the animation has a startDelay
that is greater than zero then the animation will start after the delay has passed.
There are two ways of stopping a running animation. You can use either the end
method or the cancel
method. In both cases the animation will stop and can only be restarted by calling start
. The difference between end
and cancel
is the state that the animated objects will be in after the call to the method. When calling cancel
the animation will stop in its tracks, leaving the animated objects in an intermediate state. When calling the end
method the animation will effectively be fast forwarded into the final state of the animation. All objects will appear the way they would at the end of the animation.
A feature of the new API in the Kitkat realease of Android that has not received much media attention is the fact that animations can now be paused and resumed. Previously, when an animation was cancelled and left in the current state, it could only be restarted from the beginning by calling the start method. Now you can call pause
to pause the animation. Pausing will have the same visual effect as cancel. The difference is that a call to resume
will resume the animation from the paused state.
Let’s see how this looks in practice. We create a new activity and hold the animation as a private member. We initialise the animation in the onCreate method.
private ObjectAnimator anim; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.property_animations_flow); ImageView someImage = (ImageView) findViewById(R.id.some_image); anim = ObjectAnimator.ofFloat(someImage, "rotation", 0, 360); anim.setDuration(1000); anim.setRepeatCount(5); anim.setRepeatMode(ObjectAnimator.RESTART); }
The animation is a simple rotation animation that repeats a full 360 degrees image rotation five times. The image that is rotated has been defined in the layout XML file and given the id some_image
. The layout also defines 5 buttons labelled Start, End, Cancel, Pause, and Resume. The buttons are linked to the following five methods.
public void startAnimation(View view) { anim.start(); } public void endAnimation(View view) { anim.end(); } public void cancelAnimation(View view) { anim.cancel(); } public void pauseAnimation(View view) { anim.pause(); } public void resumeAnimation(View view) { anim.resume(); }
These methods will simply call the corresponding methods on the ObjectAnimator anim
. The two animated gifs below demonstrate the behaviour. The left movie shows the difference between end
and cancel
. Note how cancel
leaves the image in the rotated position while end
will advance the image to its final state.
The movie on the right shows the effect of pause
and resume
. Note how a call to pause
will stop the animation in its tracks, just like a call to cancel
. But now we can resume the animation by calling resume
.
Querying Animation Status
Sometimes you would like to query the state of an animation. This can be done using the following three methods.
boolean isStarted() // added in API 14 boolean isRunning() boolean isPaused() // added in API 19
isStarted
will return true after the start
method has been called but the animation has not finished or has not been cancelled. Note that isStarted
requires a minimum API of 14. The method will return true
even during the duration of any initial start delay. This is in contrast to the return value of isRunning
. isRunning
will return true
only when the animation is actually running and has not finished.
The isPaused
method was added in API 19. This accounts for the fact that an animation can be paused and resumed. If it is paused then isPaused
will return true
, otherwise is will return false
.
To demonstrate the outcome of these inspector methods, we will extend the example by displaying three text fields that show the status of the animation. These are defined as TextView
members of the Activity class
private TextView isStartedText; private TextView isRunningText; private TextView isPausedText;
In the onCreate
method we add three lines that retrieve the text views from the layout.
isStartedText = (TextView) findViewById(R.id.status_is_started); isRunningText = (TextView) findViewById(R.id.status_is_running); isPausedText = (TextView) findViewById(R.id.status_is_paused);
We create a method that will update the content of the text fields from the animation status.
public void setStatusTexts() { isStartedText.setText("isStarted = " + anim.isStarted()); isRunningText.setText("isRunning = " + anim.isRunning()); isPausedText.setText("isPaused = " + anim.isPaused()); }
We then call the setStatusTexts
method after initialization and every time we modify the animation flow. For example, the method cancelAnimation
is changed as follows.
public void cancelAnimation(View view) { anim.cancel(); setStatusTexts(); }
The results can be seen in the left movie below. Again, I created one movie for the End and Cancel control and one movie for the Pause and Resume control. Note that the state of the animation is identical after pressing End or Cancel even though the visual appearance of the animated object is different. This means that you can’t distinguish between animations that have been stopped by calling end
and those that have been stopped by calling cancel
. In both cases isStarted
and isRunning
will return false
.
The right movie above shows the effect of pausing and resuming the animation. When pausing an animation isPaused
will return true
. After resuming the animation isPaused
will again return false
. Note that the animation status does not change when the animation finishes naturally. Surely, isStarted
and isRunning
should return false
after the end of the animation. The answer is, they would return false is we called them. In the example we are not updating the status texts at the end of the animation because we have don’t know when the animation has finished. To be able to update the status texts, or any other part of the application, when the animation status changes we will need the AnimatorListener
and the AnimatorPauseListener
. Using listeners in property animations will be the topic of the next post in this series.
The complete code for this tutorial can be downloaded from GitHub.
Follow the author
