ANKUR KOTWAL: Hi, I'm Ankur Kotwal, and I'm an engineer on
the Android Developer Relations team
CHRIS BROADFOOT: Hi, I'm Chris Broadfoot.
I work on the Google Maps Android API team.
ANKUR KOTWAL: Today we're going to talk to you about the
Maps API for Android.
And we're going to cover a few things.
But to start with, let's talk about animation.
If you have a look at the sample code for the Maps API,
you'll see that we use handlers to animate markers
and for other purposes, too.
So what we're going to talk about today is how you can use
handlers for backward compatibility but use some of
the newer APIs, ie the property animation framework,
to have an even better experience.
So let's switch to the tablet, and let's just see a basic
marker animating.
All we're doing is where we tap, we just generate a
polyline from the source to destination.
Just tell the marker to move there.
CHRIS BROADFOOT: Yup.
ANKUR KOTWAL: So here, we've accomplished
what we wanted to.
But as I said in Gingerbread and older, what we would do is
animate the marker's position using a handler.
So let's have a look at some code that shows
us how we do this.
CHRIS BROADFOOT: OK, so we'll be showing you three ways of
animating a marker.
And each of these methods will have the same parameters--
so the marker itself, the final destination lat long, so
that's its final point, and a lat long interpolator, which
we'll talk about a little bit later.
So from Gingerbread and before, we need to do a little
bit of setup to set up our animation handler.
So first of all, we get the start position just by calling
get position on the marker.
And then again, some of that's set up, so just the start time
and our animation duration.
So here's the meat of the animation.
So this runnable gets called every 16 milliseconds while
the animation is in progress.
The t variable is the portion that we
are through the animation.
And we're also using an interpolator.
And so these are available before Ice Cream Sandwich and
Honeycomb as well.
So this is great for like a accelerate/decelerate
interpolation or a bouncing interpolation.
And then we just go ahead and call that set position on the
marker with its new value.
ANKUR KOTWAL: And you'll see at the end of the handler,
what we do is we re-invoke the handler after 16 milliseconds.
And of course, that magic number is used so that we can
get 60 frames per second.
Now one of the downsides to this is that we are doing this
asynchronously to the Android UI rendering thread.
So what we can do is use the property animation framework,
and we're going to shift to the next one and see in the
value animator how we can synchronize those.
CHRIS BROADFOOT: OK, so from Honeycomb onwards, we can use
value animator, as Ankur said.
So here we still have to do a little bit of setup.
We get the marker's starting position.
But the value animator can give us the animated fraction.
So this is the combination of how far the animation is
through and also the interpolator.
So any accelerate, decelerate is applied to that as well.
And so we just again call set position on that.
ANKUR KOTWAL: So the onAnimationUpdate override, it
gets invoked as the next frame is being prepared.
So literally, that's your opportunity to do whatever
changes you want to make.
And then the frame will get drawn.
Unlike the handler, which is just going to happen every 16
milliseconds regardless of when you're drawing your next
frame, this happens synchronized with that
rendering framework.
Now the interesting thing is, or important thing is, you
want to make sure you complete your execution within 16
milliseconds, otherwise you're going to miss that draw, and
you're going to get jank or jitter.
The actual animation of the value, we're not really using
that, as you can see.
We say ignored.
Because we're animating from zero to one, but we're not
actually utilizing that at all.
CHRIS BROADFOOT: So let's talk about Object Animator, which
is also available from Honeycomb upwards.
But Ice Cream Sandwich adds some other
nice options, I suppose.
So here we're using an object animator.
So if you see down on this line, we just create an object
animator of the marker and its property position.
We're passing in a type evaluator, which basically
tells the animation framework how to animate between custom
object types.
So in this case, it's a latitude longitude object.
And we just passed in the final position.
So there's no need to call marker.getPosition at the
start of the animation, which is quite nice.
So the type evaluator is very simple.
In fact, it's very similar to our lat long interpolator
object, which we'll show you in the next section.
ANKUR KOTWAL: So the other advantage that I can see here
is that we've actually got significantly less code to do
this now than when we started.
So you can obviously group properties.
You can group different objects in here as well.
So you can animate things in bundles.
CHRIS BROADFOOT: This works well with a property's value
holder, for example.
ANKUR KOTWAL: Yeah.
All right, so that's animation.
Now let's switch back to our tablet.
Chris, why don't you walk us through the next problem?
CHRIS BROADFOOT: OK, so our animation is very simple.
We're just animating the latitude and longitude values
of the lat long object separately.
So this has some problems on the surface of the earth,
where things wrap around the date line.
So at the 180th longitude, it's actually the same point
as minus 180 longitude.
So you'll notice if we try to animate across, the marker's
going to go all the way around the world instead of taking
the shortest path.
So we can fix this very simply.
Let's go over to the code.
So here's our broken interpolator.
It just takes the lat and long and takes a linear
interpolation of each value.
And our fixed one just figures out whether we should take a
shorter path or not.
So it just sees if the distance it needs to travel is
more than 180 degrees.
ANKUR KOTWAL: Let's switch back to the tablet and just
see what happens there.
So this is the broken one.
We're traveling around the world to get to
that shortest distance.
If we just switched to our fixed one, you'll notice that
we get that path.
CHRIS BROADFOOT: Yeah.
So it's very simple.
So you may notice that the marker doesn't exactly follow
this polyline that we've added to the map.
So the polyline that we're using has a geodesic property,
which means that it's taking the shortest path on the
surface of the earth, as opposed to a straight line on
the surface of the map.
So if we wanted our marker to follow the polyline, we can
use similar spherical mathematics to do this
interpolation instead.
ANKUR KOTWAL: So switching back to the laptop.
CHRIS BROADFOOT: Yeah, so this one's
quite a bit more complex.
You probably won't be writing this function yourself.
Instead you should probably just copy and paste it or
include the Android Maps Utils Library.
But basically, it just does this spherical math.
So if we switch back to the tablet--
ANKUR KOTWAL: Here it is broken, just to show you that
it's actually not following that line.
CHRIS BROADFOOT: Yep.
ANKUR KOTWAL: And let's switch to spherical.
CHRIS BROADFOOT: Yup.
So let's go near the poles, for example, where this is
more obvious.
So you can see there's quite a large bow.
And the marker's following the line exactly.
ANKUR KOTWAL: And if we go back to the broken one, you'll
see that it literally--
CHRIS BROADFOOT: Line goes straight across.
So the spherical method is very useful if you want this
marker to follow a line, like we are here, or if your
markers have some sort of actual geographic importance,
like perhaps a plane on the map or something like that.
Just animating the latitude and longitude separately is
fine for short distances, or if you don't really care about
any geographic properties, and is probably quite a bit faster
than the spherical methods.
There's a lot of maths in there.
ANKUR KOTWAL: Yup, so please do check out the code
that we have here.
We'll put an annotation into the video.
CHRIS BROADFOOT: It's going to be on Ankur's face.
ANKUR KOTWAL: And we hope you found this useful.