Search code examples
androidgoogle-mapsinfowindowmarkermanager

maintain custom marker info window on configuration change


Question

Why does my custom infowindow not 'inflate' after a configuration change?

Summary

I have an app that places a marker on a map using MarkerManager, and sets a custom info-window using setInfoWindowAdapter.

After loading the app and clicking on the marker, the info-window correctly displays my custom layout.

However, after rotating the app so that the configuration changes, selecting the marker no longer displays the custom info-window, and instead only displays the generic 'title'.

What have I missed in all the hours of reading and tutorials that means I'm not correctly implementing this?

Code

Here is a stripped-down version of my app to replicate the issue

MapsActivity

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    MarkerManager.Collection mMarkerManagerCollection;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

        if(savedInstanceState == null){
            mapFragment.setRetainInstance(true);   // maintains the map fragment on orientation changes
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        MarkerManager mMarkerManager = new MarkerManager(mMap);

        mMap.setInfoWindowAdapter(mMarkerManager);

        mMarkerManagerCollection = mMarkerManager.newCollection("myMarker");
        mMarkerManagerCollection.setOnInfoWindowAdapter(new GoogleMap.InfoWindowAdapter(){

            @Override
            public View getInfoWindow(Marker marker) {
                return null;
            }

            @Override
            public View getInfoContents(Marker marker) {
                View v = getLayoutInflater().inflate(R.layout.info_window, null);

                TextView tv = (TextView) v.findViewById(R.id.myTv);
                tv.setText("hello world, this is my marker");
                return v;
            }
        });


        // Add a marker in Sydney and move the camera
        LatLng sydney = new LatLng(-34, 151);

        MarkerOptions options = new MarkerOptions()
                .position(sydney)
                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED))
                .flat(true)
                .title("Marker in Sydney");

        Marker marker = mMarkerManagerCollection.addMarker(options);
        marker.setTag("test marker");
        mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
    }
}

info_window.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView
            android:layout_width="93dp"
            android:layout_height="96dp"
            android:id="@+id/rect_load"
            android:padding="2dp"
            android:src="@mipmap/ic_launcher"
            />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">


            <TextView
                android:id="@+id/myTv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="myText"/>

        </LinearLayout>
        
    </LinearLayout>

</LinearLayout>

Gradle

compile 'com.android.support:appcompat-v7:25.0.0'
compile 'com.google.android.gms:play-services:9.8.0'
compile 'com.google.maps.android:android-maps-utils:0.4'
compile 'com.google.android.gms:play-services:9.8.0'

Solution

  • The problem is that you are creating and populating a new MarkerManager on each onMapReady call. As onMapReady gets called when the orientation changes but you are not removing old markers, the map has two markers on the same position.

    When you click the marker after the orientation changes, the old marker is triggered and you see the default behaviour (show title). If you click the marker again you will see your info window.

    One possible solution can be calling mMap.clear(); on the onMapReady before adding markers.