Join David Gassner for an in-depth discussion in this video Displaying customized info windows, part of Adding Google Maps to Android Apps.
- A map markers default Info window displays a title and a snippet with default font families and text sizes. But you can create your own custom Info windows by combining an XML layout file with a little bit of code. In this portion of my project, Custom Windows, I've already created an XML layout file. I'll find it under the Resources folder, under Layout, and its name is info_windows.xml. It starts with a linear layout with the orientation set to horizontal.
In the first object, going from left to right, is an Image View. The Image View displays the same marker that I previously used as the Marker icon itself. Then there's a linear layout with an orientation of vertical, and there are four Text View controls stacked from top to bottom, displaying the locality, the latitude, the longitude, and the snippet. And notice that the Text View for the locality is in a larger font size. I can look at this in Design View but it won't tell me much because I don't have any dummy text in there.
So I'm just going to implement this code and see how it looks in the real app. I'll go to my Main Activity class. When I first initialize the map, in the initMap method, I'm getting the reference to the map from the SupportMapFragment class and then I'm just notifying the rest of the application that the map can be used by returning a true value. But this is also the right place to set up a custom Info window. When you set up the custom Info window. you're setting up an interface with a callback method.
At runtime, when a user requests the Info window by touching a marker, a method will be called automatically by the framework and it's up to you to then fill in the view by inflating a layout, and assigning values, just like you would with an activity, or a dialog. So I'll place this new code here, after assigning the value of mMap. Now the rest of the code I'm going to execute depends on that variable not being null, so I'll add another conditional block nested inside the first one, and I'll set the condition to mMap not equal to null.
And then here's where I'll put all of my Info window set up code. Next, I'll set something called an Info Window Adaptor. This will be an anonymous implementation of an interface. The interface is named Info Window Adaptor and it's a member of Google Maps, so the code looks like this, mMap.setInfoWindowAdaptor, and then within the parentheses I'll pass in New, GoogleMap.InfoWindowAdaptor.
When I select that I see an error condition, so I'll use an intention action and implement the methods of the interface. And I see that there are two, named getInfoWindow, and getInfoContents. I'll select those and that adds the two methods. At runtime, when the user asks for an Info window, first the getInfoWindow method will be called. If you want, you can pass back the entire presentation of an Info window.
Or, you can, as is the default code here, return a null value, and then the framework will call getInfoContents. The view that you pass back from this second method will be wrapped in the default frame of a standard Info window, and that's where I'm going to put my code. I need to construct a View object, so I'll declare it with View as the Type, and I'll set the name as just V, and then I'll call getLayoutInflator.inflate.
I'll pass in the ID of my layout file, R.layout.info_window. And then I'll pass in a null value as the View Group. Next I'll get references to all the Text View components that are inside the layout. I'll take a look at that file again, and see that the IDs are TV locality, TV wrap, TV long, and TV snippet. So I'll set up the first one, with Text View, and I'll give it a variable name of tvLocality and then I'll call the views findViewById method, and again, this is just like setting up an activity, and I'll pass in R.id.tvLocality.
I'll then add casting to the Return value and now I have a reference to that Text View. Now I'll handle the other three Text Views. I'll duplicate that line of code a few times and then I'll go through and change both the Variable Name, and the ID of the Text View object I'm looking for. This one will be for the Latitude. The next one will be for the Longitude.
And the fourth one will be for the Snippet. The next step is to get the Latitude, and Longitude of the current marker. I'll get that information from the Marker object that's passed into this method. This is the argument right here. I can get that information by calling a method of the marker object named getPosition. It returns a lat long object. I'll name it LatLng, initial lowercase character, and I'll assign it with marker.getPosition.
Now I'm ready to display some text. I'll start with tvLocality.setText, and I'll pass in marker.getTitle. So whatever title was assigned to the marker the user selects, that's what will be displayed by this Text View object. Now once again, I'll duplicate that line three times and then I'll go through and set the text. This one will be for the Latitude.
And I'll pass in LatLng.Latitude. And because that's a Float value I'll prefix it with a string of Latitude. I'm going to delete the next line and instead, duplicate the Latitude line, and I'll change this one to Longitude. And I'll make sure to change the ID of the Text View I'm using to display the value.
And then for this last statement, I'll set the Text Display of tvSnippet, and I'll call marker.getSnippet. And finally, I'll return the view object. And so that's all the code I need. I'm starting by inflating the layout file, then I'm getting references to all of the Text View objects, and then I'm setting their display, getting the information from the marker that the user selected. And now I'm ready to run the code.
When the app comes to the screen I'll type in NY and search and that moves the map to the location I selected, and then I'll touch the Info window and there's my customized Info window displaying the icon, and displaying the locality in a large font, and all of the other values in a smaller font. You can customize the Info window as much as you want and you could add more logic to look up the location and display a graphic that's associated with that particular location.
Now it's important to note that the Info window is not interactive. If you add buttons or other interactive components, they might show up, but when the user touches them, nothing's going to happen. An Info window is for display only. But using an Info Window Adaptor you can customize it and make it look the way you want for your application.
- Getting a Google Maps API key
- Adding the Google Play services library
- Setting a map's initial state
- Geocoding addresses
- Displaying different types of maps
- Working with the current location
- Adding and customizing map markers
- Drawing on maps
- Preparing map apps for deployment