PAUL SAXMAN: Hello, welcome.
My name is Paul Saxman, and welcome to the premiere
episode of The Mobile Experience.
In this series, we'll be covering UI guidelines and
design principles for building location-based
applications with maps.
In this episode in particular, we'll be covering how to
implement a interface for browsing a list of places
using a scrollable view interface, or
ViewPager in Android.
In iOS, the equivalent would be a UIScrollView.
Using pagination or paging.
To demo, this technique, we're going to actually build an
application over a series of episodes.
We're calling this application the Walkway app.
The principle it's designed on are based on what we presented
in Google I/O--
that was a walker app--
in the show called Making Location Meaningful with the
Google Maps APIs.
This application covers a number of use cases.
The primary use case is displaying a view, or showing
a route for exploring a location.
The user can view a list of places along this route.
They can choose which places they want to maybe stop by or
maybe not stop by.
They can also tweak the types of places they want to see.
So if they want to stop by cafes or museums, they can put
that in there.
Or maybe they don't want to stop by these places.
They'd rather stop by the bar.
So basically, they establish a route and also establish a
series of places they want to stop by.
Another thing that we might add to this application in the
future is maybe a social aspect.
We could do something like Ways for Walking.
It might be kind of fun.
But that would definitely be in a much
further future episode.
So with that, why don't we jump into a quick demo of the
application the way it is right now.
You can see here, the application takes some
inspiration from the Google Maps Mobile application.
And that's actually on purpose.
They put a lot of effort into building a nice user interface
that is single-handed exploration.
You can see on the bottom here, we have a ViewPager.
The ViewPager is this is a white box on the bottom.
And right now, it says the ferry building.
And if you see, if I take this ViewPager and I slide across,
you see a new place in the map, and you also see new
place in the ViewPager.
So right now it's saying exploratorium.
So this ViewPager, the point of this is it allows the user
to navigate through a list of places very rapidly just using
their thumb.
Like I said, this is a single-handed interface, which
is very nice for if you're carrying a bag, you're walking
along carrying your coffee or other beverage, and you just
want to quickly browse through this list of
places on the map.
Another thing you'll notice about this interface as well
is that we have a nice big map.
The purpose of the big map is to allow the user really easy
navigation with their thumb on the map as well.
Smaller map's actually a little harder to get to more
accurate positioning.
And also, the larger map lets us zoom out to a high enough
level so that we can see of the places at one time.
So this is just a pre-canned list of places that I put in
the application.
But future episodes will maybe integrate with the Places API
to do a dynamic list.
And allow the user, like I said, to add and remove their
own places.
Another thing you'll notice is when I'm sliding the ViewPager
is that there's only one marker highlighted on
the map at a time.
So the highlighted marker corresponds to what's
displayed in the ViewPager.
And the interesting thing about this is this eliminates
the need for using info windows.
So the bad thing about info windows is if the map is
scrolled off to the side and the marker is no longer
displayed, you no longer see the last
thing that you selected.
But using the ViewPager, you actually still see the place
in the bottom of the screen.
I can get back to the map.
So as you see, as I'm scrolling through the list of
places in the ViewPager, one markers
highlighted at any one time.
The other thing that I did here is these dot markers--
or measle markers, of you may--
these are also touchable or clickable.
If I click on one of these, it takes focus, and ViewPager
updates its position.
So the nice thing about this is the user can actually
navigate entirely on the map.
They don't actually have to use the ViewPager if they
don't want to.
So they can explore the area spatially using the map
instead of exploring the places using the ViewPager.
Another thing that's implemented here is if the
user clicks on the highlighted marker.
You see you get this nice zoom-in effect.
This is the detail mode.
You get the same effect if you touch or just click the
ViewPager for the highlighted place.
It zooms in and shows detailed view.
In a future episode, what we can do is maybe add more
detailed information about the place.
For example, on the Google Maps Mobile application, what
that does is when you click on the place, it pulls up a
drawer where you can actually see more information.
We're not going to try to implement everything that the
Google Maps Mobile application does.
But where it makes sense in this application, we may
integrate those designs.
What I did with the back button is it
has two states now.
One, if we're zoomed in in a detailed mode, you see here if
I click the Back button, it's going to zoom back out to the
full map mode.
So essentially, the first mode is resetting the map.
The second mode is actually going to reset the ViewPager
so the user can get back to the original
location on the list.
Because remember, this is a walking path.
So we're going from the ferry building to the very last
place, which is Yerba Buena Gardens.
So at some point, the user may want to actually get back to
the very first place.
And using the back button's a very nice way to do that.
If I were building this application in iOS, which
doesn't have a Back button, you probably want to put some
kind of UI control maybe in the title bar or in the menu
bar, or an overlay over the map that allows the user to
actually reset their map state.
So with that, I'm going to start jumping into a little
bit of code to show you how this is
implemented in Android.
This part'll get a little bit boring for you iOS developers.
But we'll potentially implement the same interface
in iOS in a future episode and share that
code with you as well.
So if we take a look at the code now for this application
in Android, you can see here that this is the layout file
for the main interface.
So we only have one interface here.
If you remember the application, I've removed
everything--
all the superfluous UI controls,
like the action bar--
for the time being.
So all we have is the map and the ViewPager at the bottom.
You see this frame layout.
This just allows me to do overlays on top of the map.
There's just a very subtle shadow
effect over the ViewPager.
And the bottom here is where you actually see
the ViewPager itself.
It's very simple to implement.
It's part of the Support Library, which means it's
supported across a number of different Android releases.
And essentially, all you need is a position for it and the
layout width and height.
I've actually specified the height.
I fixed the height to 85 DPI, which was a nice height for
thumb swiping.
When you take a back to the interface on the phone, it was
a little bit sparse.
There was just a little bit of text in there.
Eventually, we can add more information to that ViewPager,
similar to how we would
potentially use an info window.
So if we go back, actually, to the code itself, instantiating
the ViewPager.
I'm just going to pull it out of the layout.
Give it a PagerAdapter.
And I'll discuss the PagerAdapter in a little bit.
The PagerAdapter is how you get the data and the views
instantiated for the ViewPager.
And here, I implemented an OnPageChangeListener.
So this is how I'm capturing these events as the user's
swiping from left to right.
And I'm using this event to change the focused marker.
So I'm taking the previously focused marker, I'm shrinking
it down to a dot marker.
And the inverse, taking the new highlighted marker and
blowing it up.
Let's take a look at the PagerAdapter.
So there's several different versions of this.
There's the PagerAdapter, which is the base class.
And then there's two concrete implementations of this.
There's the FragmentPagerAdapter and the
FragmentStatePagerAdapter.
The latter two require you to instantiate fragments.
These are actually for the pages in the view, ViewPager.
I chose to use just a PagerAdapter to instantiate
views, not fragments, just because it's a lot simpler for
this use case.
Future episodes, though, I'd probably want to think about
migrating to the FragmentStateAdapter and
actually making these pages first-class citizens or
reusable components.
Right now, they're just baked into the application.
But this is a very simple, quick and easy way to get up
and running with these pages.
As you can see, in the application right now, it's
just essentially the name of the place.
Here, I'm actually attaching an
OnClickListener to the View.
That's how I'm allowing the user to actually zoom in to
get the detailed view.
A click event on the view, in the ViewPager, allows us to
zoom in to that particular place on the map.
So coordinating between the map and the ViewPager.
The way I'm actually doing all this coordination in this code
between the ViewPager and the map is using indices.
Because the ViewPager, when you get events on the
ViewPager, it's by position, what page
you're on in the ViewPager.
I use that position to go back to my collection of places or
markers to actually update them in the map.
And that's this code following below.
The next thing that we'll probably want to look at is
the marker itself.
So the markers are fairly simple.
All I did here, though, is I added OnClickListener or
onMarkerClick click to the map.
That allows me to do two things.
If the user clicks the currently highlighted marker,
you get the zoom-in feature, or the detail view.
If it's not the currently selected one, then we go
through that process of highlighting it
and updating it.
So essentially, just telling the ViewPager
to update its item.
Then the ViewPager gets that event and does its work to
change which marker is highlighted.
So that's pretty much it for the code.
There's a few things that I'll probably want to add to this.
Let's take a look at the application one more time.
So a few things.
I ran a little mini usability study.
I took this application and gave it
to a few of my friends.
I said, play around with it.
Tell me what you think.
And they gave me, actually, some really good feedback.
A few people isn't an extensive study.
But it's always good when you have somebody else besides
yourself, or somebody that you aren't working really closely
with on an application to take a look and tell
you what they think.
So one bit of feedback that I got is it's not always obvious
that the ViewPager is an interactive
component on this interface.
When you first start the application, you just see
whatever the default was here.
This ferry building.
It's not necessarily apparent that you can actually swipe
left and right on ViewPager.
So one trick that we might think about implementing here
to actually make it apparent to the user that it is
interactive is on start up, you can give it a little bit
of a wiggle.
So have the ViewPager maybe move left and right, or
actually iterate through a few items to show
the user how it works.
You could do this only the first couple of times on start
up, and then not do it anymore.
And actually, I've seen that implementation on another
application.
It was the Open Table application that
has a similar interface.
They do that on start up.
Another thing that you could do is put in angle brackets on
the right- or left-hand side of the ViewPager.
That generally indicates that there's more information, give
the user some kind of clue that they can find more
information to the left or right.
So it'd be a nice interface thing to add to this
application.
Pager looping.
So another bit of feedback that I got is that when you to
the beginning or end of this list of places, it can be a
little bit frustrating when you can't continue on.
You might want to, instead of stopping at the last page or
the last marker, actually just flip over and start at the
beginning again.
I don't know if that's necessarily easy to implement
with the ViewPager.
I think it might be more easy if you had just a scrollable
view of some sort.
But one thing we could do is potentially just, when the
user gets to the end, automatically take it back to
the beginning.
You could add a number of repeated places, repeated
views to the ViewPager.
So as the user keep scrolling on there,
you're getting new views.
But essentially, these are views of the same data.
A number of different things we could do.
But yeah, definitely it seems like a little bit of a
frustrating thing, to get to the end of this list and not
be able to start over.
And one last thing.
So as you can see, what's happening here is, as I'm
scrolling through this list of places in the ViewPager, I'm
actually re-centering the map.
So the highlighted markers in the center of the map.
Which is a very nice design, because you always have what's
important in the middle.
However, we wouldn't always have to reposition the map if
the newly highlighted marker is already near the center.
We could just highlight that marker as the
user scrolls through.
And that allows, if the user has repositioned the map, if
they're looking at a neighborhood that's more
relevant, or an area of the map that's more relevant to
them, and they scroll to a new marker that's on that place on
the map already, we're not actually
re-centering the map for them.
I actually played around with that a little bit.
It wasn't too easy to do off the top of my head.
Just because what you have to do is you can tell which
markers are on the current map.
But you can't tell how much padding is
around those markers.
So for example, if one of these markers was off to the
edge, I could tell if it was on the map.
But I can't tell, if I inflate the marker or make the marker
bigger, if the markers is visible on the map.
So there's a few things that I might try to play around with
that for a future episode.
But this is how we're going to keep it for the time being.
We don't think zoom is necessarily a bad thing.
But we always want to make this a little bit better.
There's a few things that I was going to--
a few things that are interesting to mention about
this interface as well.
That I think we'll also work on or potentially talk about
in a future episode.
You can see that I took the action bar out.
That's only just because I don't have any other in-app
navigation, presently, in this application.
If I didn't want to have other activities, I'd definitely
want to have an action bar.
Otherwise, I'd also consider putting in a navigation bar in
a future episode.
For example, if I want to browse, or have other commands
that you could do.
Let's say if you want to add or remove places from the list
of places on the map, or redo your search, a navigation bar
would be nice.
And the way to get to the Navigation bar would be via
the Action bar.
Or actually, a drawer handle.
But we'll play around with that in future episodes.
The other thing that's interesting with this
interface, you can actually see in the code, is these dot
markers are actually shape drawables.
So they're simple enough as vector graphics, or vector
shapes, that I can define them as an XML shape drawable.
They're just a circle with a gradient inside.
That allows me to actually scale them to any size that I
want, dynamically, if I want to.
And also, if I do want to change the color of the style
of these markers, I don't have to go back to my drawing tool
and regenerate raster images for that.
I could just go in and tweak the color settings.
I thought about actually doing it even more dynamically.
So for example, with the highlighted marker.
These are the default markers they come with the maps SDK.
You specify the hue that you want to use.
You take that hue and apply it to the marker gradient so that
you use the hue of the main marker to define the color of
the markers, but not too much work.
So having the shape drawable, though, is actually a nice
thing to do.
Thanks for joining me.
I hope you found this episode helpful.
The code that I demoed today is actually all
available on GitHub.
The link is below.
We're going to continue to build this application out in
future episodes.
So if you have any feedback, you can provide either on
GitHub, in the GitHub repository, or
on our Google+ page.
We're happy to get all your feedback and potentially
implement those ideas in future shows.
So thanks again.