TourGuide - Virtual Sightseeing
This application is a simple application with a Spinner select a location and view that location on a MapView. Click here to download the complete source.
Here is what this TourGuide application looks like:

The main class "TourGuide" is a MapActivity. Only a MapActivity is permitted to create a MapView, but for some reason, you are not permitted to use a MapView XML element. However, I found a workaround in this post on android-developers. If you use a <MapView> element you will get an error, but if you use a <view> and separately specify the class as "com.google.android.maps.MapView" it will work.
Here is the main.xml layout file that we'll use for this application:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <view class="com.google.android.maps.MapView"
- android:id="@+id/map"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"/>
- <Spinner android:id="@+id/spinner1"
- android:layout_alignParentTop="true"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:drawSelectorOnTop="true"
- android:paddingTop="10dip"
- android:paddingBottom="10dip" />
- </RelativeLayout>
Our layout is a RelativeLayout with a MapView that fills the whole screen, and a spinner floating on top of it at the top of the screen. Now we must create our MapActivity in TourGuide.java:
- { "Bill Gates' house", "-122.242135,47.627787" },
- { "Shepshed Dynamo Football Grounds", "-1.286913,52.774472" },
- { "Michael Jackson's Neverland Ranch", "-120.088012,34.745527" },
- { "Leaning Tower of Pisa", "10.396473,43.723002" },
- { "Airplane Graveyard", "-110.834026,32.150899" },
- { "Grand Canyon", "-112.298641,36.142788" },
- { "Lake Kariba", "27.990417,-17.235252" },
- { "White House", "-77.036519,38.897605" },
- { "World Trade Center site", "-74.012253,40.711641" },
- { "Las Vegas Strip", "-115.162296,36.133347" } };
- private Spinner spinner;
- private MapView map;
- private MapController mc;
- @Override
- super.onCreate(icicle);
- mc = map.getController();
- ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(
- for (int i = 0; i < locations.length; i++)
- adapter.addObject(locations[i][0]);
- spinner.setAdapter(adapter);
- spinner.setOnItemSelectedListener(selectListener);
- gotoSelected();
- }
- private OnItemSelectedListener selectListener = new OnItemSelectedListener() {
- gotoSelected();
- }
- };
So first I've just defined an array of Strings called location starting on line 18. It's a 2d array with each entry having the label for the location and the latitude/longitude. I grabbed these from http://www.satellite-sightseer.com/ 's most popular destinations. The exact coordinates can be found in the kml file for each one.
In the onCreate() function we first initialize our MapView and Spinner. After that we create an ArrayAdapter to use with the Spinner and add each label from the locations array to this ArrayAdapter. Once it's filled in we set it as the ArrayAdapter for the Spinner and then call gotoSelected() to move the map to the currently selected item (Area 51 when you first start this app in this example). Finally we setup the Spinner's OnItemSelectdListener so that it will call gotoSelected() when a new item is selected.
Here is the gotoSelected() function that will move our map to the correct location:
- public void gotoSelected() {
- int pos = spinner.getSelectedItemPosition();
- mc.animateTo(p);
- mc.zoomTo(18);
- if (!map.isSatellite())
- map.toggleSatellite();
- map.invalidate();
- }
To go to a location we must create a Point using the latitude and longitude in microdegrees (10^-6). So we get the coordinates from the locations array string for the selected object and split it to get the seperate longitude and latitude as a double. Once we have these we must multiply each one by 1,000,000 to get it's value in microdegrees. Now that we have the Point object we can use a MapController to go to our point using animateTo(Point) and a zoom level of 18 using zoomTo(Int). Finally we make sure that we are showing satellite view instead of map view, and we call map.invalidate() to force it to redraw.
With this you would be able to go view different objects and pan around using the touchscreen. But pressing "I" or "O" doesn't zoom like it normally does, so we must handle those keys to allow the user to zoom in and out. We can simply override the onKeyDown function, and here is that function:
Very simple switch statement here, if the user pressed "I" we zoom in, and they press "O" we zoom out.
I hope you enjoyed this simple application to demonstrate using a MapView. Obviously it's not ideal to just have a bunch of hard-coded locations, but it could be extended to pull and parse some XML from a source on the internet or could be populated by performing a Search on keywords. If you have any questions/comments/suggestions check out the tutorials forum.
Good luck in the challenge!!
Comments
MapView is visible with the grey grid but no map is visibe
Thanks for the post, it has proven to be exactly what I needed. One question though, how would you go about switching the xml so that the map was on top and the table row was on bottom? I tried to switch them in the main.xml, but lost the table row when I did that. Then I tried adding the layout_location="top" to the view, but it resulted in the same layout as in your tutorial.
Any suggestions would be greatly appreciated.
This works well, actually works better than the code above because the spinner and button float over the MapView :)
Alternatively you could do this in XML to get the mapview happening:
<com.google.android.maps.MapView
id = "@+id/dest_map"
layout_location = "Center"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
/>
Cheers
S
Nice tip, thanks
Post new comment