Animation / Animation Set / AnimationListener / Transition

Manual Layout Transitions – Part 1

Layout transitions are an important aspect of Material design as they help to indicate the user flow through an app, and help to tie visual components together as the user navigates. Two important tools for achieving this are Activity Transitions (which we’ll cover in the future) and Layout Transitions which we have covered on Styling Android before. However Layout Transitions are only supported in API 19 and later. In this series of articles we’ll look at how we can implement some nice transition animations even when we don’t have access to the transitions APIs.

Before we begin, it is worth pointing out that there is a back-port of the transitions API which offers compatibility back to API 14. However, I have decided to avoid this because I’ve never tried it; I prefer to stick with core Android APIs for blog articles; and the purpose of this series is to actually explore the techniques that the transitions API itself use to make it easy to roll your own.

In the previous series covering the Dirty Phrasebook app there were some simple animations when transitioning in and out of input mode:

I elected to implement these manually for reasons of backwards compatibility, so let’s begin with a look at how these animations work before progressing on to some more complex examples.

Let’s start with a quick look at the layout (this is a simplified version of the layout used in Dirty Phrasebook to make it easier to understand the various components):

The key components that we need to be aware of in the animations are the Toolbar, The CardView with the ID input_view, the ImageView with the ID input_done, and the FrameLayout with the ID translation_panel. The only other view that we need worry about is focus_holder which is an invisible view used to hold the focus away from the only other focusable control in the layout. By toggling the focus between the EditText and focus_holder we toggle in and out of input mode, and it is this transition which starts the appropriate animations.

The animations are going to move input_view upwards to cover the Toolbar, fade in input_done, and fade out translation_panel. The reverse of this will be done as the user exits input mode. In the video you can see these happening.

Let’s now take a look at MainActivity:

This is pretty straightforward: All it does is set up the Toolbar, and then set up the focus logic. The logic for creating the transitions is performed in Part1TransitionController and I’ve elected to abstract this logic out in to a separate class to enable us to easily swap implementations for future parts to this series. Part1TransitionController actually subclasses an abstract base class named TransitionController which contains some common logic:

This handles the onFocusChanged() event and calls an appropriate abstract method when we enter and exit input mode. It also contains an AnimatorListener class which we’ll use to ensure that the IME gets hidden when we exit input mode. The other thing is that there is an AnimatorBuilder instance which actually constructs some atomic property animators which we’ll use repeatedly, so let’s also take a look at that:

There are two basic animator that are constructed here: One is a translation animator which will effectively move a view up and down by modifying its translationY attribute, and the other will change the opacity of a view by modifying its alpha attribute. There are also a couple of utility function which wrap the alpha animator method and provide some convenience methods for transitioning from fully opaque to fully transparent, and vice versa.

All that remains is to look at Part1TransitionController to see how all of this is tied together:

Here we override the two abstract methods from the base TransitionController class. In both cases we find the appropriate views from the Activity. In enterInputMode() we build an AnimatorSet consisting of a property animator which will move inputView up by the height of the Toolbar, to transition inputDone from transparent to opaque, and to transition translation from opaque to transparent. In exitInputMode() we do the opposite of these, and also add an ImeCloseListener instance to hide the IME once the animation is complete.

That’s it. Hopefully by breaking this down in to some manageable pieces we can see how we can quite easily create some quite complex transitions by simply combining a few basic property animators.

However, we’re not going to stop there. This example is pretty straightforward, but the TransitionController instance implements the logic of which types of Animator get applied to which Views. Consequently is actually a long way short of the functionality that the transitions API offers us. In the next article we’ll change this a little to actually introspect the View states and construct the Animators dynamically rather than doing them manually as we have here.

The source code for this article is available here.

© 2015, Mark Allison. All rights reserved.

CC BY-NC-SA 4.0 Manual Layout Transitions – Part 1 by Styling Android is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Permissions beyond the scope of this license may be available at http://blog.stylingandroid.com/license-information.

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *