[English]
...
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.
...