Skip to content

Animations

Inspire Coding edited this page Oct 29, 2020 · 150 revisions

Overview

Android supports powerful animations for both views and transitions between activities. There are three animation systems that work differently for different cases but the most important are Property animations. Property animations allow us to animate any property of any object from one value to another over a specified duration.

These can be applied to anything within the Android application. This is typically used for any dynamic movement for views including position changes, rotations, expansion or coloration changes.

Animations like many resources for Android can be defined both through XML resources as well as dynamically within the Java code.

Animation Types

There are actually three distinct animation frameworks for Android:

Powered by these animation frameworks, there are five relevant types of animations:

  • Property Animations - This is the animation of any property between two values. Frequently used to animate views on screen such as rotating an image or fading out a button.
  • Activity Transitions - Animates the transition as an Activity enters the screen when an Intent is executed.
  • Fragment Transitions - Animates the transition as a fragment enters or exits the screen when a transaction occurs.
  • Layout Animations - This allows us to enable animations on any layout container or other ViewGroup such as LinearLayout, RelativeLayout, or ListView. Using the Transitions API (for Android 4.4 devices and above), the animations to the view changes can be specified. For lower versions, layout animations can still be enabled, but there is no way to dictate how the transitions occur.
  • Drawable Animations - Used to animate by displaying drawables in quick succession

Material Animation Principles

With the release of Android 5.0, Google has released detailed animation design guidelines which documents important principles to consider when integrating animations and motion into your application. There are four core principles outlined:

  • Authentic motion - Motion in the world of material design is not only beautiful, it builds meaning about the spatial relationships, functionality, and intention of the system.
  • Responsive interaction - When a user interacts with an app; beautiful yet perfectly logical things happen, the user feels satisfied—even delighted.
  • Meaningful transitions - Carefully choreographed motion design can effectively guide the user’s attention and focus through multiple steps of a process or procedure and avoid confusion.
  • Delightful details - Animation can exist within all components of an app and at all scales, from finely detailed icons to key transitions and actions. All elements work together to construct a seamless experience and a beautiful, functional app.

Review these principles for a detailed look at how to think about animations in a way that aligns with a material app.

Property Animations

Property animations were a more recent Android feature introduced in 3.0. The primary motivations for the introduction of the property animations system are outlined in this post from 2011 introducing property animations.

Common properties commonly animated on views include:

Property Description
alpha Fade in or out
rotation, rotationX, rotationY Spin or flip
scaleX, scaleY Grow or shrink
x, y, z Position
translationX, translationY, translationZ (API 21+) Offset from Position

In the past, the way to use animations compatible with pre-3.0 Android versions is to use NineOldAndroids for all our property animations. Nine Old Androids has now been deprecated and no longer being supported but can still be used by adding this line to your app/build.gradle file:

implementation 'com.nineoldandroids:library:2.4.0'

A library that simplifies common animations is called AndroidViewAnimations and makes certain common animations on views much easier to achieve. This library is definitely worth a look.

Using ObjectAnimator in Java

We can use the ObjectAnimator method to execute simple animations for a particular property on a specified object:

ObjectAnimator fadeAnim = ObjectAnimator.ofFloat(tvLabel, "alpha", 0.2f);
fadeAnim.start();

This code will execute the animation to fade out the button. Notice that the "alpha" is designated as a string type. The ObjectAnimator relies on reflection and uses the button's getAlpha() and setAlpha() methods to perform the animation.

Simple Fadeout

We can also use the properties system in 4.0 to execute property animations on common properties using:

ObjectAnimator fadeAltAnim = ObjectAnimator.ofFloat(image, View.ALPHA, 0, 1);
fadeAltAnim.start();

This is considerably faster because this property check doesn't require as much slow runtime reflection. Properties supported include ALPHA, ROTATION, ROTATION_X, ROTATION_Y, SCALE_X, SCALE_Y, TRANSLATION_X, TRANSLATION_Y, TRANSLATION_Z, X, Y, Z in order to improve performance on these animations.

Setting Duration or Repeat on Property Animation

This code above will fade the specified view to 20% opacity. We can add additional behavior such as duration or repeating the animation with:

ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(tvLabel, "scaleX", 1.0f, 2.0f);
scaleAnim.setDuration(3000);
scaleAnim.setRepeatCount(ValueAnimator.INFINITE);
scaleAnim.setRepeatMode(ValueAnimator.REVERSE);
scaleAnim.start();

Setting Interpolation

Whenever we define a property animation, we should also consider the rate of change of that animation. In other words, we don't just want to consider the value to change a property to but also the trajectory of the movement. This is done by specifying a TimeInterpolator on your ObjectAnimator:

ObjectAnimator moveAnim = ObjectAnimator.ofFloat(v, "Y", 1000);
moveAnim.setDuration(2000);
moveAnim.setInterpolator(new BounceInterpolator());
moveAnim.start();

The result of this is a different rate of motion:

Bounce

Common pre-defined interpolators are listed below:

Name Description
AccelerateInterpolator Rate of change starts out slowly and and then accelerates
BounceInterpolator Change bounces right at the end
DecelerateInterpolator Rate of change starts out quickly and and then decelerates
LinearInterpolator Rate of change is constant throughout

There are several other time interpolators which can be reviewed.

Listening to the Animation Lifecycle

We can add an AnimatorListenerAdapter to manage events during the animation lifecycle such as onAnimationStart or onAnimationEnd:

ObjectAnimator anim = ObjectAnimator.ofFloat(v, "alpha", 0.2f);
anim.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        Toast.makeText(MainActivity.this, "End!", Toast.LENGTH_SHORT).show();
    }
});
anim.start();

Choreographing Animations

We can play multiple ObjectAnimator objects together concurrently with the AnimatorSet with:

AnimatorSet set = new AnimatorSet();
set.playTogether(
    ObjectAnimator.ofFloat(tvLabel, "scaleX", 1.0f, 2.0f)
        .setDuration(2000),
    ObjectAnimator.ofFloat(tvLabel, "scaleY", 1.0f, 2.0f)
        .setDuration(2000),
    ObjectAnimator.ofObject(tvLabel, "backgroundColor", new ArgbEvaluator(),
          /*Red*/0xFFFF8080, /*Blue*/0xFF8080FF)
        .setDuration(2000)
);
set.start(); 

This results in the following:

Animation 3

We can also animate sets of other animator sets:

// Define first set of animations
ObjectAnimator anim1 = ObjectAnimator.ofFloat(tvLabel, "scaleX", 2.0f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(tvLabel, "scaleY", 2.0f);
AnimatorSet set1 = new AnimatorSet();
set1.playTogether(anim1, anim2);
// Define second set of animations
ObjectAnimator anim3 = ObjectAnimator.ofFloat(v, "X", 300);
ObjectAnimator anim4 = ObjectAnimator.ofFloat(v, "Y", 300);
AnimatorSet set2 = new AnimatorSet();
set2.playTogether(anim3, anim4);
// Play the animation sets one after another
AnimatorSet set3 = new AnimatorSet();
set3.playSequentially(set1, set2);
set3.start();

Here's one more example of a choreographed set of animations:

// Create two animations to play together
ObjectAnimator bounceAnim = ...;
ObjectAnimator squashAnim = ...;
// Construct set 1 playing together
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).with(squashAnim);
// Create second animation to play after
ObjectAnimator fadeAnim = ObjectAnimator.ofFloat(view1, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
// Play bouncer before fade
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();

See the Property Animation official docs for more detailed information.

Using ViewPropertyAnimator in Java

We can also do property animations in an even simpler way using the ViewPropertyAnimator system which is built on top of the ObjectAnimator. It also enables faster performance as described in this blog post and provides a convenient way of doing animations.

Without Support Library

If we do not need the rely on the ViewCompat#animate support v4 library and only need to support Android v3.0 devices and above, we can invoke animate() directly on any view with:

Button btnExample = (Button) findViewById(R.id.btnExample);
btnExample.animate().alpha(0.2f).xBy(-100).yBy(100);

The animate method has many properties that mirror the methods from the ViewPropertyAnimator class including changing many possible properties such as opacity, rotation, scale, x&y positions, and more. Here's a more complex animation being executed:

btnExample.animate().alpha(0.5f).rotation(90f).
  scaleX(2).xBy(100).yBy(100).setDuration(1000).setStartDelay(10).
  setListener(new AnimatorListenerAdapter() {
      @Override
      public void onAnimationStart(Animator animation) {
          Toast.makeText(MainActivity.this, "Started...", Toast.LENGTH_SHORT).show();
      };
  });

This applies multiple property animations in parallel including opacity change, rotation, scale and modifying the position of the button. Here we also can modify the duration, introduce a start delay and even setup a listener at the beginning or end of the animation.

Using the Support Library

If we want to be able to compile the code to run on pre-ICS devices, we can leverage the support library's ViewCompat.animate static method instead. If you are an Android Studio user, first add the following dependency to your app/build.gradle file:

implementation 'com.android.support:support-v4:24.2.0'

We can now run concurrent animations with the following:

Button btnExample = (Button) findViewById(R.id.btnExample);
ViewCompat.animate(btnExample).alpha(0.2f).xBy(-100).yBy(100);

The support v4 library is used to enable devices back to API 11 to execute the code. However, the animations are simply ignored on pre Android v4.0.3 devices according to this finding. To have the animations run, we need to use NineOldAndroids.

NineOldAndroids

If we wish to use the ViewPropertyAnimator and have animations run on Android pre-v3.0 devices using the now deprecated NineOldAndroids project, this import statement should be used:

import static com.nineoldandroids.view.ViewPropertyAnimator.animate;

If we want to fade out a button on screen, we can pass the button view into the animate() static function and then invoke the alpha method:

Button btnExample = (Button) findViewById(R.id.btnExample);
animate(btnExample).alpha(0);

This will automatically create and execute the animation to fade out the button:

Simple Fadeout

Using XML

We can also use property animations from XML. All we have to do is create an XML file that describes the object property animation we want to run. For example, if we wanted to animate a fade out for a button, we could add this file to res/animator/fade_out.xml:

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="alpha"
    android:duration="1000"
    android:valueTo="0" />

Now we can load that XML file into our Activity and execute an animation with:

Animator anim = AnimatorInflater.loadAnimator(this, R.animator.fade_out);
anim.setTarget(btnExample);
anim.start();

And that's all! We've now executed our predefined XML animation. Here's a more complicated animation in res/animator/multi.xml that applies multiple animations to the button in parallel:

<?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:valueTo="0.5" >
    </objectAnimator>
    <objectAnimator
        android:propertyName="rotation"
        android:valueTo="90.0" >
    </objectAnimator>
    <objectAnimator
        android:propertyName="scaleX"
        android:valueTo="2.0" >
    </objectAnimator>
    <objectAnimator
        android:propertyName="translationX"
        android:valueTo="100.0" >
    </objectAnimator>
    <objectAnimator
        android:propertyName="translationY"
        android:valueTo="100.0" >
    </objectAnimator>
</set>

and now let's execute this on the button by inflating the XML animation description:

Animator anim = AnimatorInflater.loadAnimator(this, R.animator.multi_button);
anim.setTarget(tvBlah);
anim.setDuration(1000);
anim.setStartDelay(10);
anim.addListener(new AnimatorListenerAdapter() {
     @Override
     public void onAnimationStart(Animator animation) {
          Toast.makeText(MainActivity.this, "Started...", Toast.LENGTH_SHORT).show();
     };
});
anim.start();

This results in the following:

Complex Animation

See more details in the Property Animation topic guide and the Animation Resource guide.

Custom Animations with ValueAnimator

In certain cases, instead of animating the property of an object directly (i.e alpha) as shown above, we might need finer-grained control over the animation at each step of execution. In these situations, we can use a ValueAnimator and setup a custom listener to adjust the view as the animation executes:

// Construct the value animator and define the range
ValueAnimator valueAnim = ValueAnimator.ofFloat(0, 1);
// Animate over the course of 700 milliseconds
valueAnim.setDuration(700);
// Choose an interpolator
valueAnim.setInterpolator(new DecelerateInterpolator());
// Define how to update the view at each "step" of the animation
valueAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  @Override
    public void onAnimationUpdate(ValueAnimator animation) {
      float animatedValue = (float) animation.getAnimatedValue();
      // Use the animated value to affect the view
  }
});
// Start the animation if not already running
if (!valueAnim.isStarted()) {
  valueAnim.start();
}

See the ValueAnimator for more information. Note that in most cases we can use an ObjectAnimator as shown above but the value animator is a lower-level construct that can be used when we do not want to animate the property of an object directly.

View Animations

View animations is a slower and less flexible system for animation that predates the property animation system that was introduced later. Property animations are generally preferred but let's take a look at the older system and how to apply animations using the original XML syntax.

The primary motivations for the introduction of the property animations system are outlined clearly in this post from 2011 introducing property animations. Some of the major differences include:

  • The old view animation system only supported move, fade, scale, and rotate, whereas the new one provides a more extensible framework (i.e. animating background color, gradients, or even marker map locations).

  • The old system only supported View objects (i.e. Button, TextView, ListView, etc.) but the new Property animations can support any objects such as drawables.

  • The old system would not actually update the location after a move animation, requiring manual code to update to the new position. This issue has been fixed in the new system.

See this Google I/O talk discussing some of the limitations in the older view animation system.

There have been misconceptions that Android did not use dedicated hardware (GPU's) to perform animations in the old view system. This point has been debunked by one of Google's engineers. When the new Property animations systems was announced along with Android v3.0, support for hardware acceleration for common views and widgets was also added, making the overall experience seem smoother.

Using XML

We can define our view animations using XML instead of using the Property XML Animations. First, we define our animations in the res/anim folder. You can see several popular animations by checking out this Android Animation XML Pack.

For example, a value animation XML file might look like this for fading in an object in res/anim/fade_out.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true" >
    <alpha
        android:duration="1000"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:fromAlpha="1.0"
        android:toAlpha="0.0" />
</set>

Now, we can load that animation within an activity and apply this to a view:

// Inflate animation from XML
Animation animFadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out);  
// Setup listeners (optional)
animFadeOut.setAnimationListener(new AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {
        // Fires when animation starts
    }

    @Override
    public void onAnimationEnd(Animation animation) {
       // ...			
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
       // ...			
    }
});
// start the animation
btnExample.startAnimation(animFadeOut);

This results in the following:

Simple Fadeout

See more details in the View Animation Resource guide or this more detailed tutorial.

Activity Transitions

In addition to property animations for views, we can also manage the animations and transitions for Activities as they become visible on screen. We do this by managing the transitions around the time we trigger an intent. The basic approach is that right after executing an intent with startActivity, you call the [overridePendingTransition](http://developer.android.com/reference/android/app/Activity.html#overridePendingTransition\(int, int)) method such as:

Intent i = new Intent(MainActivity.this, SecondActivity.class);
startActivity(i);
overridePendingTransition(R.anim.right_in, R.anim.left_out);

The first parameter is the "enter" animation for the launched activity and the second is the "exit" animation for the current activity. These animations can be any XML view animation files such as the animations in our XML Pack. For example, right_in might be defined in res/anim/right_in.xml as:

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/linear_interpolator">  
  <translate 
      android:fromXDelta="100%p" 
      android:toXDelta="0" 
      android:duration="500"/>
</set> 

This would move the X position of the new window from off the screen sliding in from the right (100%p means the Activity should start at a position equal to the full width of the window). We might then define left_out in res/anim/left_out.xml with:

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/linear_interpolator">  
  <translate 
      android:fromXDelta="0" 
      android:toXDelta="-100%p" 
      android:duration="500"/>
</set> 

This causes the parent activity to slide off screen to left. When these animations run together, it creates the effect that the new activity is pushing the old one off the screen while sliding in. In order to control the "back" animation transition as well, we need to create a left_in.xml and right_out.xml that reverse the values of left_out.xml and right_in.xml:

left_in.xml:

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/linear_interpolator">  
  <translate 
      android:fromXDelta="-100%p" 
      android:toXDelta="0" 
      android:duration="500"/>
</set> 

right_out.xml

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/linear_interpolator">  
  <translate 
      android:fromXDelta="0" 
      android:toXDelta="100%p" 
      android:duration="500"/>
</set> 

We then use overridePendingTransition with these two XML-based animations:

public class SecondActivity extends Activity {
    // onBackPressed is what is called when back is hit, call `overridePendingTransition`
    @Override
    public void onBackPressed() {
        finish();
        overridePendingTransition(R.anim.left_in, R.anim.right_out);
    }

    // to handle activity transitions for Up navigation add it to the onOptionsItemSelected
    // as below 
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        // This refers to the Up navigation button in the action bar
        if (id == android.R.id.home) {
            finish();
            overridePendingTransition(R.anim.left_in, R.anim.right_out);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

This results in the following:

Activity Transition

Activity Transitions in Lollipop

The Transitions API (only for Android 5.0 and above) introduces a new way of performing activity transitions, which obviously is not backwards compatible with older Android devices but provides the foundation for performing layout animations within activity view hierarchies. You can create different types of XML tags res/transition include slide, fade, explode, autoTransition, and recolor. For instance, a slide right could be defined as slide_right.xml:

<slide xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:slideEdge="right"
    android:duration="1000"/>

We could then inflate this transition using the TransitionInflater class:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // inflate transition XML & set exit transition
        Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.slide_right);        
        getWindow().setExitTransition(transition);

        // inflate xml here

Note that we set the exit transition of the activity. There are actually 4 different transitions that work in pairs: exit/enter and return/reenter. The exit transition should be declared on the departing activity, and the enter transition should be declared on the incoming activity. If no return and reenter transitions are specified, then the transitions used will be played back in reverse.

We also need to change the entering activity as well with a slide_left.xml:

<?xml version="1.0" encoding="utf-8"?>
<slide xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:slideEdge="left" />
public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // setup before inflating
        Transition a = TransitionInflater.from(this).inflateTransition(R.transition.slide_right);
        getWindow().setEnterTransition(a);
    }

}

One particular change is that startActivity needs to be called with a special bundle:

Intent i = new Intent(MainActivity.this, SecondActivity.class);
// options need to be passed when starting the activity
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
startActivity(i, options.toBundle());

Also, if you need to navigate back to the previous screen, use finishAfterTransition() instead of finish(). Normally clicking the back button already calls this method for you.

You can also control what parts of the activity transitions are excluded from this animation sequence, especially for shared elements between screens. See this section for more details.

Browsing Transition Samples

You can see several complete examples of activity transitions in the following resources:

Check out these above to get a deeper understanding of how to create custom and unique transitions. In Android 5.0 and above the ability for activities to "share elements" was introduced allowing an element in on activity to morph into an element within the child activity. Check out our Shared Element Activity Transition guide for more details.

Modifying the Default Transitions

The default entrance and exit animations for activities can be customized as part of a theme by modifying res/styles.xml with a custom Animation.Activity style as shown below:

<!-- Customize `android:windowAnimationStyle` for theme -->
<style name="AppTheme" parent="AppBaseTheme">
    <!-- ... -->
    <item name="android:windowAnimationStyle">@style/CustomAnimation.Activity</item>
</style>

<style name="CustomAnimation.Activity" parent="@android:style/Animation.Activity"> 
    <item name="android:activityOpenEnterAnimation">@anim/slide_in_right</item>
    <item name="android:activityOpenExitAnimation">@anim/slide_out_left</item>
    <item name="android:activityCloseEnterAnimation">@android:anim/slide_in_left</item>
    <item name="android:activityCloseExitAnimation">@android:anim/slide_out_right</item>
</style>

Refer to this stackoverflow post for more details.

Fragment Transitions

Similar to activities, we can also animate the transition between fragments by invoking the [setCustomAnimations](http://developer.android.com/reference/android/app/FragmentTransaction.html#setCustomAnimations\(int, int)) method on a FragmentTransaction. The animations are simply view animation XML files as used for activity transitions above. For example, suppose we want the fragment to slide in from the left and push the old fragment out. First, let's define the custom view animations starting with res/anim/slide_in_left.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="-50%p" android:toXDelta="0"
        android:duration="@android:integer/config_mediumAnimTime"/>
    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
        android:duration="@android:integer/config_mediumAnimTime" />
</set>

and then res/anim/slide_out_right.xml as well:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="0" android:toXDelta="50%p"
     android:duration="@android:integer/config_mediumAnimTime"/>
    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
      android:duration="@android:integer/config_mediumAnimTime" />
</set>

Now we just have to configure the animations of the fragment transaction before we replace the fragment or call commit:

// Create the transaction
FragmentTransaction fts = getSupportFragmentManager().beginTransaction();
// Configure the "in" and "out" animation files
fts.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
// Perform the fragment replacement
ft.replace(R.id.fragment_container, newFragment, "fragment");
// Start the animated transition.
ft.commit();

This results in the following:

Fragment Transition

Compatibility Note: The animation files explained above are used in conjunction with support fragments. Keep in mind that if you are not using support fragments, you need to use object animations instead as explained on StackOverflow.

Note that Android has built-in animations with R.anim that can be used as well by reference android.R.anim such as:

FragmentTransaction fts = getSupportFragmentManager().beginTransaction();
fts.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
fts.replace(R.id.fragment_container, newFragment, "fragment");
fts.commit();

Read more about Fragment Transitions in this detailed article. You can even check out the source code of those animations.

Extended Note: Check out this stackoverflow post if you are looking to animate the appearance of a DialogFragment.

Layout Animations

Animating on Start

A particular animation can be specified when the layout first appears on screen. This can be done by using the android:layoutAnimation property to specify an animation to execute.

First, let's define an animation we'd like to use when the views in the layout appear on the screen in res/anim/slide_right.xml which defines sliding in right from outside the screen:

<set xmlns:android="http://schemas.android.com/apk/res/android"  
      android:interpolator="@android:anim/accelerate_interpolator">
    <translate android:fromXDelta="-100%p" android:toXDelta="0"
            android:duration="1000" /> 
</set>

and now we need to create a special layoutAnimation which references that animation:

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
        android:delay="30%"
        android:animationOrder="reverse"
        android:animation="@anim/slide_right"
/>

and now we need to apply this layoutAnimation to our Layout or ViewGroup:

<LinearLayout 
    ...
    android:layoutAnimation="@anim/layout_bottom_to_top_slide" />

and now when you launch the application, the views within this layout will slide in from the right. See more information about layout animation in this guide by linkyan or in this layout animation tutorial or in the ui action layout tutorial.

Animating Changes

Layout Change Animations allow us to enable animations on any Layout container or other ViewGroup such as a ListView. With layout animations enabled, all changes to views inside the container will be animated automatically. This is especially useful for ListViews which causes items to be animated as they are added or removed.

In the past, the only way to animate changes within a layout was to set the animateLayoutChanges property on any ViewGroup within the XML:

<LinearLayout
  ...
  android:animateLayoutChanges="true">
  
  <ListView android:id="@+id/list"
    android:animateLayoutChanges="true"
    ...
  />

</LinearLayout>

The android:animateLayoutChanges property enables a default animation if no further customization is made.

With the introduction of the Transitions API framework, the animation sequences can now be controlled as well. See this guide for more details.

Animated Images

In certain cases, we want to be able to display animated images such as an simple animated GIF. The underlying class for making this happen is called AnimationDrawable which is an XML format for describing a sequence of images to display.

One of the simplest ways to display an animated gif is to use a third-party library. Glide is an easy way to display a local or remote gif into an ImageView. First, let's add Glide to our app/build.gradle file:

dependencies {
    ...
    implementation 'com.github.bumptech.glide:glide:3.6.0'
}

Next, setup an ImageView in the the activity i.e activity_main.xml:

<ImageView
    android:id="@+id/ivGif"
    android:contentDescription="Gif"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

For local GIFs, be sure to put an animated gif into the res/raw folder for displaying. Next, we can convert and load the GIF into the ImageView within the activity i.e MainActivity.java using Glide:

// MainActivity.java
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Find the ImageView to display the GIF
        ImageView ivGif = (ImageView) findViewById(R.id.ivGif);
        // Display the GIF (from raw resource) into the ImageView
        Glide.with(this).load(R.raw.my_gif).asGif().into(imageView);
        // OR even download from the network
        // Glide.with(this).load("https://i.imgur.com/l9lffwf.gif").asGif().into(imageView);
    }
}

and now we have this:

GIF

You can also check out the popular android-gif-drawable library for another solution. An alternative method is simply to use a WebView.

Material Animations

In Android 5.0, several new animation features were introduced including:

Note that these animations require lollipop or newer and do not work on devices with an Android version less than API 21. Around 70% of devices have at least lollipop running (April 2017), so the time spent using one of these animations requires thought to determine if it is worth the effort. Refer to this Material Animations sample app for detailed explanations with examples.

Particle Effects

Use the third-party Leonids library for simple particle effects. Particle systems are often used in games for a wide range of purposes: explosions, fire, smoke, etc. This effects can also be used on normal apps to add elements of playful design. Here's an example of particle motion:

Particles

Precisely because its main use is games, all engines have support for particle systems, but there is no such thing built-in for standard Android UI. Instead we can use Leonids by reviewing this tutorial for further details.

Libraries

The following animations library provide easy ways to plug-in animations into your app:

References

Finding these guides helpful?

We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.

Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.

Clone this wiki locally