Wednesday, December 26, 2012

Using InfoWindowAdapter Part 1: getInfoContents

This is the first part of my next tutorial for Google Maps Android API v2.
It's about using the InfoWindowAdapter to make awesome looking InfoWindows for your Marker.

Here I'm going to show you how to implement this adapter and how to implement the method getInfoContents(Marker marker). This will only change what's inside the InfoWindow and not how the window itself looks. In this simple example I'm simply going to add an image to the InfoWindow, change the title a bit and add a String from a custom object to it.

You might want to check my previous post on adding an object to a marker if you haven't seen it yet, I'll continue using that project for this tutorial as well.

This is how it should look when you've correctly implemented everything:

I've changed my EventInfo class a bit to add an String called "type" to it. Some of you asked for this code so I'm posting the class here:

public class EventInfo {

 

 private LatLng latLong;

 private String name;

 private Date someDate;

 private String type;

 

 public EventInfo(LatLng latLong, String name, Date someDate, String type) {

  super();

  this.latLong = latLong;

  this.name = name;

  this.someDate = someDate;

  this.type = type;

 }

 

 public LatLng getLatLong() {

  return latLong;

 }

 public void setLatLong(LatLng latLong) {

  this.latLong = latLong;

 }

 public String getName() {

  return name;

 }

 public void setName(String name) {

  this.name = name;

 }

 public Date getSomeDate() {

  return someDate;

 }

 public void setSomeDate(Date someDate) {

  this.someDate = someDate;

 }



 public String getType() {

  return type;

 }



 public void setType(String type) {

  this.type = type;

 }

}
So I've also made a small change in the setUpEventSpots() to initiate the EventInfo objects:
EventInfo firstEventInfo = new EventInfo(new LatLng(50.154, 4.35), "Right now - event", new Date(), "Party");

  EventInfo secondEventInfo = new EventInfo(new LatLng(51.25, 4.15), "Future Event", new Date(1032, 5, 25), "Convention");

Now let's setup a layout file for our contents. It's just a normal xml-file. I've placed an ImageView in it, with the launcer icon. You can change this picture if you want. For example use a picture of the object that the marker represents. Here's the code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="wrap_content"

  android:layout_height="wrap_content"

  android:orientation="horizontal">

  <ImageView

    android:id="@+id/ivInfoWindowMain"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_marginRight="5dp"

    android:adjustViewBounds="true"

    android:src="@drawable/ic_launcher">

  </ImageView>

  <LinearLayout

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:orientation="vertical">

    <TextView

      android:id="@+id/txtInfoWindowTitle"

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:layout_gravity="center_horizontal"

      android:ellipsize="end"

      android:singleLine="true"

      android:textColor="#ff000000"

      android:textSize="14dp"

      android:textStyle="bold"/>

    <TextView

      android:id="@+id/txtInfoWindowEventType"

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:ellipsize="end"

      android:singleLine="true"

      android:textColor="#ff7f7f7f"

      android:textSize="14dp"/>

  </LinearLayout>

</LinearLayout>

Just have a good look at this code and check the screenshot above to compare.

Next up, let's finally use the InfoWindowAdapter :-)
I've added this code at the end of my setUpEventSpots() method:

mapFragment.getMap().setInfoWindowAdapter(new InfoWindowAdapter() {

   

   private final View contents = getLayoutInflater().inflate(R.layout.content, null);

   

   @Override

   public View getInfoWindow(Marker marker) {

    //Only changing the content for this tutorial

    //if you return null, it will just use the default window

    return null;

   }

   

   @Override

   public View getInfoContents(Marker marker) {

    

    EventInfo eventInfo = eventMarkerMap.get(marker);

    

    String title = marker.getTitle();

             TextView txtTitle = ((TextView) contents.findViewById(R.id.txtInfoWindowTitle));

             if (title != null) {

                 // Spannable string allows us to edit the formatting of the text.

                 SpannableString titleText = new SpannableString(title);

                 titleText.setSpan(new ForegroundColorSpan(Color.RED), 0, titleText.length(), 0);

                 txtTitle.setText(titleText);

             } else {

                 txtTitle.setText("");

             }

             

             TextView txtType = ((TextView) contents.findViewById(R.id.txtInfoWindowEventType));

             txtType.setText(eventInfo.getType());

             

    return contents;

   }

  });

Try this out and if you're having any problems, just leave a comment below and I'll see what I can do.
Be sure to check back for part 2 where I'm going to make a custom window for the InfoWindow, perhaps I'll try something like a circle or something. I don't know yet.
It should be online somewhere in the next two days.

Happy Programming

11 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Hello,

    Its a nice tutorial. But i am really confused on the use of Info window, as i am working on the app which is developer a year before and i need to upgrade it.

    My requirement is -

    1. I should be able to customize marker Image(Depending on what image i get from server).

    2. Create Custom InfoWindow where i need to show Image, And text.

    3. When i click on the Infowindow i should be navigated to other Activity depending on the Marker Id.

    I have created a custom Class where i am storing all the data which i need to pass to custom class object to marker.


    Please help me resolve my question..

    Thanks in advance.

    ReplyDelete
    Replies
    1. Have you looked at my other posts on Adding custom data to a marker?

      Delete
    2. yes, i have seen , but i am not able to organize how to go ahead after adding markers.

      I am not able to concrete InfoWindowAdapter Interface.

      Delete
    3. I am getting null pointer exception in mFragment...

      Delete
    4. I'll explain with a quick example.

      Suppose you have an app that locates houses.

      You make a class called House and a House has someImage and someText.

      In your activity you have a HashMap markerList;

      create a method in your Activity to get a specific icon, for example:
      private Bitmap getIcon(String houseType){ if(houseType.equals("appartment") return appartmentIcon;
      if(houseType.equals("villa")return villaIcon;}

      Next:

      Put all your Houses in a list and for (House house: houses){
      marker = mFragment.getMap().addMarker(..., getIcon(house.getType()), ...);
      markerList.put(marker, house);
      }

      next:

      mFragment.getMap().setInfoWindowAdapter(){....

      View getInfoContent(Marker m){

      House house = markerList.get(m);
      //put house.getImage() and house.getSomeText() in the good views just as the example above

      ...
      }
      }

      Sorry for this quick respond but I have no time right now to check in the code...

      IMPORTANT: if you get a nullpointer on getMap() perhaps you are calling it to soon. Make sure you call it somewhere in OnStart() or something.. check activity or fragment lifecycles...

      Delete
  3. Nice example. I'm trying to implement a similar one with a shape as the layout background, so the info window is displayed with rounded corners. However, my layout is appearing inside another view, a rectangular one. Any idea what could be going on?

    ReplyDelete
  4. Did you check my next post? http://bon-app-etit.blogspot.be/2012/12/using-infowindowadapter-part-2.html

    It's about creating an info window with a custom window and custom content. This example here is only about changing the content, not the window

    ReplyDelete
  5. I see... It worked! Thank you very much!

    ReplyDelete