Hi.
I'm Chet Haase, an engineer on the Android UI Toolkit team.
Today, I'm going to talk about a new animation
feature in the KitKat release.
It's called transitions.
So the idea with transitions is actually
the idea behind a lot of the stuff
that we do which is trying to make things easier for you,
the developers of Android applications,
to get richer experiences for your users,
hopefully with less effort.
Transitions, it's kind of a simple idea.
It's basically a way for you to describe the different scenes
in your application, either beforehand as layout resource
files, or dynamically, as things change in the application,
and then use transitions to animate the changes no matter
what those changes were.
And you can step out of the way and just
let the transitions run automatically
without having to get more involved
and run these manual animations which
are more of the typical model of animating things in a UI.
Hopefully, at the end of the day,
you get richer applications experiences
by having more stuff move on the screen in an intuitive way.
Your users get richer experiences.
And they get a better understanding
of how your application actually works
because you can transition naturally
between these different scenes of your application.
And there's more animations in the world
which I'm always in favor of.
OK.
So let's take a look at some slides.
And we'll go over a very quick overview of how the API works,
what the different pieces are.
There's a lot of details that I'm skipping here,
but you are free and encouraged to check out
the details in the reference docs
and articles on developer.android.com,
and also API demos which we'll see a little bit later.
We'll take a look at some code in that.
OK.
So first, we start out with the idea of a scene.
You can think of this as a layout.
It's basically a view hierarchy that
describes what this particular scene looks like.
This could be the scene of the entire application
in a particular screen, or it could be some sub-hierarchy.
In this particular case, the scene
describes this situation where we
have a text view, an edit text, and a button.
Fairly simple.
And then we have another scene that we've
described through possibly some other layout file.
We have different text views in there, a little bit richer
text, longer details there.
But we have, again, an edit text field and a button.
And maybe these are shared components.
Maybe they moved location, possibly changed size.
But they're actually shared between the two scenes.
Wouldn't it be nice if you could help the user understand,
as they move from scene one to scene two in your application,
the changes that had occurred by fading things out that go away,
fading things in that have come into being, and moving
and resizing the shared elements between these scenes?
That's what transitions are about.
You specify these different scenes.
And then when you go to a scene, the transition
automatically kicks in and runs the necessary animations
in order to make that change, as well as
to animate the change over time.
So let's take a look at scenes.
These are the modules that you've
defined for your application, the different screens, if you
will, of state that your application will move through
over time.
You can construct these scenes in different ways.
First of all, scenes always have a root or a ViewGroup
associated with them which is basically
the hierarchy under which the scene lives
and in which transitions will take place.
So you can construct a scene directly with that root.
And then you can set an EnterAction.
And whenever that scene is entered,
you will get a callback into your Runnable
and you can run whatever code, you
want to make whatever manipulations
you want to to the view hierarchy.
Fairly straightforward.
A little bit more manual than the other ways
you can create scenes.
For example, you can create it from a ViewGroup instead.
Let's say you have inflated a hierarchy from some layout ID.
You have this ViewGroup sitting there.
You can create a scene with that ViewGroup.
So you give it basically two ViewGroups.
You can create with the root of the scene hierarchy,
as well as the root of the scene itself.
So you pass that in.
You've created a scene.
You're good to go.
So now when the scene is entered,
it will simply change the scene to be looking at that ViewGroup
instead.
You don't need to tell it what to do
to manipulate the hierarchy.
It gets that information from the ViewGroup
that you passed it in the constructor.
Finally, we have something very similar to the last one.
But instead of handing it a ViewGroup,
you hand it a layout resource ID.
And when that scene is entered, it will inflate the resource.
And it will go ahead and add that to the scene root.
Straightforward.
The layout resource also kicks in
if you create scenes implicitly in resources
which we'll see a little bit later.
You can have a Transition Manager that automatically
inflates scenes implicitly, given layout resource IDs.
And it uses the same mechanism under the hood.
Next, we can take a look at transitions.
These are the engine responsible for declaring
what it is you want to do when things change
from scene to scene in your application.
So these basically listen for changes before and after,
and compare those values.
And then based on changes that occurred to any view
in the scene hierarchy, they'll create an animator
that then gets run to animate those changes.
There's a few different ways to create transitions.
You can just create these things directly.
We have some defined in the framework already.
There's a ChangeBounds which will move and resize
objects that change between scenes.
There's a fade that will fade things in and out according
to whether they come or go between scene changes.
And then there's also a TransitionSet
which is kind of the transition equivalent of AnimatorSet.
It's basically a group.
It's a way of choreographing several different transitions.
You can create a TransitionSet and then
tell it whether, for all of its transition children,
to run those together or sequentially.
And it can also be a hierarchy of sets.
So you can have a much more complicated mechanism
that runs several transitions in parallel or one
after another to get a more interesting animation
experience.
And finally, you can load transitions
from resource files, if that's the way you go.
If you want to run it from resources,
this is how you can do it.
This one, for example, is a TransitionSet
that gets loaded that has two children automatically added
to it to listen for changes in visibility,
as well as size and location.
The resource file, maybe it's not
something you want to do from code because you're already
in code in UV.
It's easy enough to create these things on the fly.
On the other hand, this is the mechanism
that is used by Transition Manager when it inflates
a graph of the information which we'll see soon,
but not on this slide yet.
Finally, there's an idea of custom transition.
So we've defined, as I said, a couple of canonical transitions
which automatic transition will use on the fly.
There's ChangeBounds which moves and resizes views.
And there's also fade which deals with visibility
information, fades things in and out.
Fairly straightforward.
Probably the behavior you want in most cases.
But if you want to define your own transition-- for example,
if when something comes into being,
you didn't want it to fade in in the middle of the screen
where it lives, but you actually want
to slide it in from the right, then
you can write a custom transition.
You would simply subclass the transition class itself.
And then you override the three methods
that do what it is you want to do.
There's two capture methods.
One captures the values at the start when the application
code said, OK, I'm ready to do a transition.
That's the point at which you would
get a call to your captureStartValues method.
And you would go ahead and just read from the view objects
anything you wanted to that affected your transition.
So you could read the layout position, for example,
or the visibility information that you care about.
And then you get a call to the captureEndValues
when the transaction actually wants to run,
when it wants to start.
And then you finally get a call right
after that to the createAnimator function which can then
compare those values and say, OK, well,
this visibility value changed.
And that's something that I care about.
Therefore, I'm going to create an animation that
does the following-- slides in from the right
or whatever it is.
Returns that animator.
And then the transition system runs it.
So there's a lot of stuff that we just
ship with the framework for free and you can simply
use implicitly when you run a transition.
But if you want to create custom transitions, fairly
straightforward to do that.
OK.
So now you've got your scenes.
You've got your transitions.
How do you actually change scenes?
How do you go from one scene to another?
You could just enter a scene.
There's no transition involved there.
You're basically just saying, here's
the scene I want you to load.
And it will do that.
It will run the code that was in your Runnable.
It will inflate the layout resource file that you gave it,
whatever.
It'll enter the scene.
Nothing much going on there.
Certainly no interesting animations.
Or you can tell the Transition Manager to go to a scene.
And in the process of doing that,
it will use a default transition along the way.
It'll say, OK, I'm going to change into this scene.
And in the meantime, I'm going to captureStartValues,
captureEndValues, and run the default transition
for the system.
Or you can run it with a custom transition.
You can say, OK, I've defined this lovely transition
that I want to use when I'm going
between this particular scene combination, and now go ahead
and transition using one of the TransitionTo
or the go methods in the Transition Manager.
And it will actually load that new scene
and then run your custom transition along the way.
Before we get to Transitions, Simplified,
there's one other thing that I haven't mentioned here
which is the idea of a Transition Manager.
You'll usually use this just for a one-off thing where you say,
Transition Manager, I want to go to this scene
and use my custom transition here.
The other thing that it can do is
keep a whole graph of information
about all the transition combinations
that you want for all the scene combinations
that you have in your application.
We'll see a little bit of that in the demo later.
But I did want to point out one final thing here
on this last exciting slide is that
with all this information, all these different classes
to think about it, and you've got scenes
and you got transitions, but really, the idea
was to make animations simpler for most development cases.
So in general, the only method that you probably
are going to care about is this one
called TransitionManager.beginDelayedTransition.
And then give it the scene root that you
want to run the transition on.
What that does is kicks in all of the process that
is going to capture the current values.
And then it's going to spawn a layout and rendering run.
And then in the middle of that frame,
it's going to capture the end values,
figure out where things are, and then run
an automatic transition for you.
In most cases, this is all that you actually care about.
It's basically a dynamic change.
You can think of this as creating and animating
a dynamic scene.
So instead of having these pre-baked scenes
from layout resource IDs, you can basically say,
OK, I want you to run a transition, so get ready.
And then in the meantime, I'm going
to make a bunch of changes.
And then by the time those changes have actually
kicked in, measure and layout has run,
and the system is ready to draw the new frame.
Then, the transitions kick in, figure out the deltas,
figure out the changes, and create the animations,
and start the animations running.
Fairly straightforward.
One line of code.
Nice.
OK.
So now, let's take a quick look at a demo.
And this is one of the API demos that ships with KitKat.
So I would encourage you to download this from the samples.
And you can run this and play with it
to your heart's content.
Totally complicated and interesting demo.
So we defined four scenes here.
And the scenes use custom views.
So no particular reason why.
These could be buttons.
I happened to make them colored rectangles instead.
So as we change between the scenes,
you can see we're resizing, we're
repositioning these things.
And we can just change on the fly.
We're canceling.
We're interrupting.
We're running other transitions.
So fairly straightforward.
Now let's take a look at the code for that demo.
So there's a few different pieces here.
First, there's some layout files.
So we have Transition Scene One.
This just has a layout.
And it has four views inside there,
positioned appropriately.
Transition Scene Two looks very similar to that.
It's just different sizes and different positions
for the colored rectangles.
Transition Three adds the complication
of also having those gray scale custom views in the middle
there.
So nothing really interesting going on in the layout resource
files.
But you'll see them referred to later in the resources
that we inflate for the Transition Manager.
We have some custom transition that we've defined.
This is simply a ChangeBounds.
Nothing really interesting here.
It's just the standard ChangeBounds
that we're going to run.
But we refer to this resource later
when we inflate the Transition Manager.
Here's a little bit more interesting one.
This is a TransitionSet.
It's going to run in the default mode
where all the transitions run in parallel.
It's going to run a ChangeBounds at the same time
as it's going to run a fade transition.
And the fade is going to be targeted at a specific view.
And we use IDs to associate with views.
So that means the fade is not generally applied
to everything on the screen, but we're saying,
hey, I want you to run this specific transition
on this specific view in the hierarchy.
Fade-out is very similar.
Although in this case, it's going
to run the transition sequentially.
So it's going to run the ChangeBounds on any things that
change position and size.
And after that's done, it's going to run the fade.
And then finally, we have a Transition Manager
which we haven't really seen yet.
This is the object that keeps a graph of what
you want to happen as you go from scene to scene
in your application.
You can define here-- I mean, if you don't need any custom
transitions, then you wouldn't care about Transition Manager.
You would just run transitions.
But if you care that when you go from scene one to scene two,
you want this particular custom transition, but from scene two
to scene three you want a different one,
this is how you would define it, at least in resource files.
So you create a Transition Manager.
And then you have several transition objects
that define the interaction you want
in any of these particular scene changes.
So we have a fromScene that refers to a layout file.
And that's implicitly going to inflate
that layout resource file and create a scene out of it.
We have a toScene.
Same thing.
It's going to create a scene from that layout file.
And then we have the transition that it's
going to refer to in another transition resource
file like the ones that we just looked at.
So that's all the resource stuff.
Now let's look at the code which is in transitions.java.
And in the API demos, you'll see this
in the Animations directory.
And it's called Simple Transitions.
And here it is.
Not a lot of code going on here.
We inflate the Transition Manager.
Well, we get the Transition Inflator.
And then we inflate the Transition Manager down here.
And we also create three scenes along the way.
And you'll note, we're only creating three scenes,
but there were actually four in the demo.
And we'll show why in a minute.
The only reason that we need the scenes in the code
here is that this is where we specified
they were going to transition to a particular scene.
We've already told the Transition Manager
what transitions to run as we go scene to scene.
And here, we're actually getting a reference to those scenes
and saying, OK, now I want to move
to scene one, scene two, scene three.
And we do that down here.
When we click on the radio button in the demo,
we get a call to one of these items.
And we say, OK, Transition Manager, I
want you to transition to the next scene.
And it'll go.
It'll load the scene.
It'll figure out the changes and run the transition
that we specified in the Transition Manager resource
file that we saw.
Finally, there is a fourth scene in there
that has nothing to do with these scene objects
that we inflated.
But instead, this is what I referred
to before as a dynamic scene because we're basically
changing the view hierarchy on the fly
and having the Transition Manager
or the transition system, in general,
basically automatically animate all the changes there.
We call the magic method, call beginDelayedTransition.
We hand it a scene root that we're going to operate on.
We call this helper method called Set newSize.
And basically, we make arbitrary changes
inside the view hierarchy.
This comes in here.
It sets some new layout parameters on the views.
This will spawn a request layout internally.
Things inside the scene root will end up being relayed out
and rerendered.
And when that happens, Transition System
noticed that things have changed,
and it runs transitions automatically.
As you saw in the demo, things move around,
things resize with this single line of code.
So that's transitions.
It's a new feature in KitKat.
I anticipate it will be worked on more as time goes on.
It's fairly straightforward and simple for now.
And hopefully, more importantly, simple
for you to use to make richer Android applications.
Thanks.