Animate all the things. Transitions in Android

“Motion provides meaning. Objects are presented to the user without breaking the continuity of experience even as they transform and reorganize. Motion in the world of material design is used to describe spatial relationships, functionality, and intention with beauty and fluidity.”
- Material Design guidelines.

In fact, the process of creating animations takes time. It’s sure tempting to just call setVisibility(View.VISIBLE) and move on to business logic of your awesome new feature, given that it’s already past all deadlines. But remember: every time you ignore opportunity to add meaningful UI transition another sad designer appears somewhere in the world.

Let’s start with some history

New animateLayoutChange parameter was introduced for ViewGroup in Android 4.0. But even with calling getLayoutTransition() and configuring some stuff inside it, it was still unstable and not flexible enough. So you couldn’t do much with it.

Imagine we have a button

After a click we want to have a text appeared below the button. Here is our layout:

Simple types of Transition

  • ChangeBounds. It animates changes to view position and size. This one moves the button in our example.
  • Fade. It extends Visibility class and performs most popular animations — fade in and fade out. In example it’s applied to TextView.
  • TransitionSet. It’s Transition that is actually a set of another Transitions. They can be started together or sequential, to change it call setOrdering.
  • AutoTransition. It’s TransitionSet that contains Fade out, ChangeBounds and Fade in in sequential order. At first, views that don’t exist in the second scene are faded out, then change bounds applied for changes of position and size, and, finally, new views appear with fade in. AutoTransition used by default when you don’t specify any transition in the second argument of beginDelayedTransition.

Backport

Everyone wants to write only one implementation that will have consistent behaviour on every Android version. Hopefully, we can achieve that while still using Transitions API. Some time ago I had found two quite similar backport libraries on githab, but they are no longer maintained and both of them missed some things that still could be backported. So, I’ve created my own library based on both of them and added a lot of new stuff for compatibility with older Android versions. All API changes from Lollipop and Marshmallow have been merged too.

What else we can do

First of all, we can change duration, interpolator and start delay for animators inside Transition:

Slide

Like Fade transition, extends Visibility class. It helps new view in scene to slide in from one of the sides. Example with Slide(Gravity.RIGHT):

Explode and Propagation

Explode is a lot like the Slide, but the view will slide in some calculated direction depending on a Transition epicenter (you should provide it with setEpicenterCallback method).

ChangeImageTransform

ChangeImageTransform. Will animate changes of image matrix. It’s useful for situations when we change scaleType of ImageView. In most cases you’ll want to use it in pair with ChangeBounds to animate position, size and scaleType changes.

Path (Curved) motion

“Real-world forces, like gravity, inspire an element’s movement along an arc rather than in a straight line.”
- Material Design guidelines.

For every Transition that operates with two dimension coordinates (for example change of view position with ChangeBounds) we can apply curved motion with setPathMotion method.

TransitionName

Let say we need to remove all views from container and add the new set of views. And some of the new elements are actually the same as they were before recreating. How we can help framework to understand which items were removed and which elements were moved to a new position? Easy. Just call static method TransitionManager.setTransitionName(View v, String transitionName) to provide any unique name depending on your data model for every view.

Scale

This one is not actually a part of Transitions API and was added by me. It allows us to animate visibility change with scale animation. Simple example with new Scale():

Recolor

Try to figure out what this one is for. Exactly! Animated change of background and/or text color.

Rotate

No time to explain, example:

ChangeText

Helps to add simple fade animation for the text changes.

Targets

Transitions are easy to configure. You can specify target views for any Transition. And only them will be animated.

  • addTarget(int targetViewId) — id of view
  • addTarget(String targetName) — do you remember about method TransitionManager.setTransitionName?
  • addTarget(Class targetType) — for example android.widget.TextView.class
  • removeTarget(int targetId)
  • removeTarget(String targetName)
  • removeTarget(Class target)
  • excludeTarget(int targetId, boolean exclude)
  • excludeTarget(Class type, boolean exclude)
  • excludeTarget(Class type, boolean exclude)
  • excludeChildren(int targetId, boolean exclude)
  • excludeChildren(Class type, boolean exclude)

Create Transition with xml

Transition can be inflated from xml. Xml should be placed in res/anim folder. Example:

Activity and Fragment transitions

Activity Transitions can’t be backported, sorry (sadpanda). A lot of logic is hidden in the Activity. The same applies to Fragment transitions. We should create our own Fragment to change transitions logic.

Custom Transitions

Transitions can be used for every purpose, for every View. Let’s try to create something unique - our own Transition.

PS

All samples from article are available as sample project in library repository.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store