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.
There are actually three distinct animation frameworks for Android:
Powered by these animation frameworks, there are five relevant types of animations:
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:
Review these principles for a detailed look at how to think about animations in a way that aligns with a material app.
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.
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.
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.
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();
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:
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.
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();
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:
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.
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.
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.
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.
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:
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:
See more details in the Property Animation topic guide and the Animation Resource guide.
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 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.
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:
See more details in the View Animation Resource guide or this more detailed tutorial.
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 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:
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.
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.
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.
Similar to activities, we can also animate the transition between fragments by invoking the setCustomAnimations 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:
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.
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.
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.
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:
You can also check out the popular android-gif-drawable library for another solution. An alternative method is simply to use a WebView.
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.
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:
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.
The following animations library provide easy ways to plug-in animations into your app: