CHET HAASE: Hi, I'm Chet Haase, an engineer on the
Android team at Google.
One of the principles of cartoon animation that we
spoke about recently at a Google I/O talk called "A
Moving Experience" is the idea that motion in our real world
is not linear.
So if you want a UI to feel more natural to the user, more
organic, more like it's a real-world application, then
maybe the motion in your application shouldn't be
linear either.
Now, we already offer this by default in all of the
animations in the platform in terms of time interpolators,
because you can set deceleration motion,
acceleration motion, overshooting.
By default, you accelerate into and out of any animation.
So the time aspect is already handled.
So that feels a little bit more natural than simple
linear interpolation.
However, the motion on the screen is not handled
automatically.
If you want to move, let's say, a view from the upper
left side of the screen down to the lower right side of the
screen, and you want it to follow a curve instead of a
straight line, it may not be immediately
obvious how to do that.
So this is why I wrote an article a
while ago on my blog.
My blog is at graphics-geek.blogspot.com.
The article is called "Curved Motion in Android."
So you can go check out that article.
It's basically most of what I'm going to be showing today.
So you can go read that for more information.
But I wanted to give a brief glimpse of how you would do
that using the existing animation APIs that we already
offer in the platform.
So we can take a look at the following demo.
Very simple--
we have a boring button on the upper left side of the screen.
And now, it's a boring button on the lower
right side of the screen.
So these are two different layouts where we determine
where the button needs to be in the two positions.
And we basically just toggle between them.
But as we toggle between them, we animate the position change
using the approach that I'll go over in the
code starting now.
OK, so in our click listener, we call this method called
Move Button here.
This simply sets the layout parameters to tell the button
to be either at the upper left or lower right--
very straightforward.
Then we add an OnPreDrawListener, which is a
technique that I use a lot in animation demos, which
basically allows layout to run from the previous change.
In this case, we set the layout parameters on the view.
Layout is going to run.
And then it's going to change the position of the button.
But before we draw that change on the screen, we're going to
figure out where the button is now.
We know where it was before, because we track that in these
oldLeft and oldTop properties up here.
And now we can figure out the delta between those, between
the x and the y values, and animate the change.
Now, if all we did was set up an animation to animate x and
animate y, it's very easy to set up.
But it's going to give you the linear motion that simply
moves the button linearly from the upper left
to the lower right.
And we really wanted the curved motion instead.
So we're going to use some helper classes in here.
We're going to use this Animator Path class that I've
defined that's similar to, but much simpler than, the path
object that we provide in the framework.
It also has a query capability that will return this array of
points, which is sort of important for the
interpolation that I needed to do with it.
So in the Animator Path, you can basically use one of three
methods to set up your path.
You can do a Move To, a Line To, and a Curve To.
So I'm going to tell the path to move to the old position of
the button, and then curve to the new
position of the button.
And the arguments to the Curve To are both the end position
as well as a couple of control points in the middle.
And this is basically defining a cubic Bezier spline between
the two points.
We have anchor points at the end and control points in the
middle that determine the motion of that object along
this curve.
In this case, it's a simple curve that's just going to go
in a simple arc down to the lower right and then back to
the upper left.
We create an Object Animator on our objects.
And we're going to animate this property called
buttonLoc, which I've defined a property setter for, which
we'll see below.
We're going to use this path evaluator, which is a class I
defined to evaluate between these
different types of objects.
One of the nice things about the property animation system
is, sure, you can animate floats and ints.
But sometimes, you have a more complex data
structure like a [? rept ?]
or a point, or in this case, these path objects, these path
points along the curve.
Then how would you interpolate along those?
Well, the system doesn't know how to.
But you can tell it how to by providing one of these type
evaluators to get a callback on every frame.
And then you simply do the interpolation for the system
and pass back the appropriate values.
And then finally, for the points that we're going to
animate between, we do a query into our animator path.
And that's going to return this array of points that
define the animation.
We set an interpolator on this thing.
And we start.
And we're all good to go.
So we can take a look at the bottom.
We have this property setter that we need to find called
setButtonLoc.
This is going to get this object called PathPoint, which
is a data structure that holds the information.
And then we simply set the TranslationX and TranslationY
property of the view according to what was in
that PathPoint object.
We can take a look at the PathPoints.
This is simply a data structure that says, what kind
of point is this?
It's a move or a line or a curve, and then has
information about those points internally.
The animator path that we saw before allows you to build up
this path of successive points and then query the points once
you're done so we can actually set up the animation on it.
And then finally, we have the type evaluator.
And the one that we defined is called Path Evaluator.
And it just uses this straightforward calculation.
So it looks like a lot of garbage going on in here.
This is actually a really simple calculation.
It's a standard spline calculation.
So given a value t, the time in this animation, we can
calculate the x and y values on the curve.
One caveat that I mention in the article as well is this is
not necessarily the motion along the curve that you want.
What you really want is, in general, to take the t value
of how far along the curve is, and use that to extract your x
and y values.
That requires a little bit more code.
I didn't want to get into it in this simple example.
The effect that you'd get by using this simplistic approach
here is, on hairpin turns, you'd go a lot faster.
So you really want to spread out that motion
evenly along the curve.
Kind of a detail--
maybe it'll matter in some of your curves.
So you should know about it.
But if you want a simple approach, here's one.
So curved motion-- in general, if you're moving stuff on the
screen that's not just going in one axis, consider moving
it in a curve to give the user more of a natural and organic
feeling for your application.
Make them feel like they're actually interacting with
something in the real world instead of just some user
interface on a boring screen.
Thanks.