In the last post I promised to continue the animations tutorial with telling you how customise your animation using interpolators and attributes that are common to all ViewAnimation objects. In this post I will be using a simple animation of a ball to illustrate these customisations.
Let’s start by creating the layout. Like in the first tutorial we define a simple FrameLayout
that contains the ImageView
.
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/ball" android:layout_width="100dp" android:layout_height="100dp" android:onClick="ballClicked" android:src="@raw/football" android:layout_gravity="center_horizontal" /> </FrameLayout>
To make the ball appear I have placed a PNG image called football.png
in the res/raw
folder. The layout_gravity
property will make the ball appear at the top centre of the screen. The onClicked
property sets the callback method to ballPressed
. This is implemented in our Activity
class.
public void ballClicked(View thumbnailView) { ImageView animatedImage = (ImageView) findViewById(R.id.ball); Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation); animatedImage.startAnimation(animation); }
Note that the animation is loaded from the resource R.anim.animation
. We will create the animation.xml
file in the res/anim
folder once we are done with the preliminaries. Of course, the layout is loaded in the activity’s onCreate()
method.
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_animation02); }
Linear Interpolator
The next step is to define the animation XML file animation.xml
. This goes into the res/anim
folder.
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/linear_interpolator" android:duration="1000" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="0" android:toYDelta="80%p" />
I have defined a simple translation animation. The ball will move from its original position to a position 80% down the height of the screen. The interpolator specified by @android:anim/linear_interpolator
. The linear interpolator moves the object with a constant velocity from the initial position to the final position.
Usually this is not the right interpolator for moving a View in the user interface because there is no acceleration or deceleration and the motion seems quite abrupt. For changing the transparency through alpha
animations, on the other hand, this is the perfect choice.
Accelerate and Decelerate Interpolators
The interpolator that has a period of acceleration at the start of the animation is the accelerate_interpolator
. To use this interpolator, simply change the appropriate line in the animation XML file.
android:interpolator="@android:anim/accelerate_interpolator"
The accelerate interpolator starts slowly but arrives at the final position at full speed. The opposite effect can be achieved by using decelerate_interpolator
. This will start at full speed but then slowly come to rest at the end position. Again, just change the line in the animation XML file.
android:interpolator="@android:anim/decelerate_interpolator"
The interpolator that combines an acceleration phase and a deceleration phase is, you guessed it, the accelerate_decelerate_interpolator
. The code for the XML file looks like follows.
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
Below are the results of replacing the interpolators in the ball animation.
Anticipate and Overshoot Interpolators
The anticipate_interpolator
starts by moving the view backwards before it accelerates forwards. This creates the effect of a slingshot. As with the accelerate interpolator, the final position is reached at full speed.
android:interpolator="@android:anim/anticipate_interpolator"
The opposite of the anticipate interpolator is the overshoot_interpolator
. Here the view starts with full speed but overshoots the target before it returns to the final position.
android:interpolator="@android:anim/overshoot_interpolator"
Combining the effects of both the anticipate and the overshoot interpolator is the anticipate_overshoot_interpolator
. The movement starts away from the target before it accelerates towards the target. It then overshoots and returns to the final position.
android:interpolator="@android:anim/anticipate_overshoot_interpolator"
Again, I have created a number of animations that illustrate the effect of the interpolators using the ball animation.
Cycle Interpolator
The cycle_interpolator
is different from the other interpolators in the sense that the view moves towards and away from the target by the same amount. The values oscillate sinusoidally between positive and negative values. Theto values of the animation are not interpreted as the final values but as the maximumamplitude of the oscillation. Choosing the cycle interpolator is as easy as before.
android:interpolator="@android:anim/cycle_interpolator"
To illustrate the effect of the cycle interpolator I had to modify the layout and the animation. Because the motion goes both ways I placed the ball at the centre of the screen. This is easily done by changing the gravity of the ImageView
in the layout.
android:layout_gravity="center"
Because the ball is now centred I also had to reduce the magnitude of the motion to 40%p
in the animation XML file.
android:toYDelta="40%p"
The cycle interpolator is very useful if you want to repeat the animation in a loop. We will see how to do that in the next section.
Repeating Animations
In many cases an animation should only be played once. This is certainly the case when you want to fade in or fade out a View. There are, however, a lot of cases where you want the animation to repeat, either a fixed number of times or indefinitely. Maybe you want to display a continuously rotating loading spinner or you want to replicate old school web design with buttons that grab the user’s attention. You can do this by using the repeatCount
and repeatMode
attributes. The value of repeatCount
tells the animation to repeat a fixed number of times.
Note: repeatCount
specifies the number of repeats, excluding the first iteration. This means that a repeatCount
of 3 will play the animation a total of 4 times.
The second attribute, repeatMode
, can be either restart
or reverse
. When set to restart
, the animation will restart from the beginning on every repeat. When set to reverse
, the animation will reverse direction for every repeat.
Reversing the animation is useful for bouncing motion between the from and the to positions. Restarting the animation is useful for continuous rotations, or when using the cycle_interpolator
. In the examples shown, I have extended the original linear_interpolator
with a repeatCount="3"
and a android:repeatMode="restart"
for the first example and a android:repeatMode="reverse"
for the second example.
I hope you enjoyed this tutorial. In the next instalment I will be talking about how to create View Animations programmatically. This will give you more freedom in specifying starting and ending positions, according to the positions of views in the current layout.
awesome article!!!
it’s been a great help for me.
No words Hats of you boss.
Very nice tutorials!!
Simply awesome. Well done.
if there’s a multiple activity app then what’ll be the process of doing the same animation method
hello
in the last example i want decelerate from the “android:toYDelta=”80%p”” in each repeat
Is there a way to reverse the animation? For instance i want to make the decelerate interpolator move the item from bottom to top, how do i do that on the xml?
I read that setting a float value on the constructor to 1.0f gets the reverse effect. I want to know how to achieve it using XML.