Thursday, December 27, 2012

Using InfoWindowAdapter Part 2: getInfoWindow

As promised, here's the second part on how to use the InfoWindowAdapter in Google Maps Android API v2. This is a sequel to my last blog post and also to the post before that. So be sure to check that out first.

In my last blog I told you how to change the contents of your InfoWindow without changing the default window layout. Now I'll show you how to change that window as well. First of all let me quote something that I read on the Android developers site:
The API will first call getInfoWindow(Marker) and if null is returned, it will then callgetInfoContents(Marker). If this also returns null, then the default info window will be used.
So this means you have to implement the contents of your InfoWindow in getInfoWindow(Marker) as well, if you want to change the window. The API will ignore what's in getInfoContents(Marker) if getInfoWindow(Marker) does not return null.

This is a screenshot of what our InfoWindow should look like:

You'll see I've copied the code of getInfoContents(Marker) of my last post and used this in getInfoWindow(Marker). I also did this with my xml layout file.

First of all, we're going to create this oval shape with the gradient blue background. We'll use this as background of our window. I've named it circle_window.xml and placed it in (one of) my drawable folder(s).


<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >

    <gradient android:startColor="#FFA1A4E3" android:endColor="#AFA1CDED"

            android:angle="270"/>

</shape>

Next I made a new layout file called custom_window.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="wrap_content"

  android:layout_height="wrap_content"

  android:orientation="horizontal"

  android:background="@drawable/circle_window"

  android:padding="15dp">

  <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>

It's basically exactly the same as in my previous post, except for two things.

  • set the oval shape as background of my layout.
  • set a padding of about 15dp so that our contents is placed nicely within our oval shape
To finish of we need to implement our InfoWindowAdapter like this:

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

   

   private final View window = getLayoutInflater().inflate(R.layout.custom_window, null);

   

   @Override

   public View getInfoWindow(Marker marker) {

    EventInfo eventInfo = eventMarkerMap.get(marker);

    

    String title = marker.getTitle();

             TextView txtTitle = ((TextView) window.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) window.findViewById(R.id.txtInfoWindowEventType));

             txtType.setText(eventInfo.getType());

             

    return window;

   }

   

   @Override

   public View getInfoContents(Marker marker) {

    //this method is not called if getInfoWindow(Marker) does not return null

    return null;

   }

  });

As always, if you have any questions, feel free to leave a comment below and I'll see what I can do.

Download source code here

Good luck!