17

I want to show an InfoWindow on markers in a Maps V2 fragment. Thing is, I want to show BitMaps that are dynamically loaded from the web with Universal Image Downloader.

This is my InfoWindowAdapter:

class MyInfoWindowAdapter implements InfoWindowAdapter {

    private final View v;

    MyInfoWindowAdapter() {
        v = getLayoutInflater().inflate(R.layout.infowindow_map,
                null);
    }

    @Override
    public View getInfoContents(Marker marker) {



        Item i = items.get(marker.getId());

        TextView tv1 = (TextView) v.findViewById(R.id.textView1);
        ImageView iv = (ImageView) v.findViewById(R.id.imageView1);
        tv1.setText(i.getTitle());


        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .delayBeforeLoading(5000).build();

        imageLoader.getMemoryCache(); 

        imageLoader.displayImage(i.getThumbnailUrl(), iv, options,
                new ImageLoadingListener() {

                    @Override
                    public void onLoadingStarted(String imageUri, View view) {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void onLoadingFailed(String imageUri, View view,
                            FailReason failReason) {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void onLoadingComplete(String imageUri,
                            View view, Bitmap loadedImage) {
                        Log.d("MAP", "Image loaded " + imageUri);

                    }

                    @Override
                    public void onLoadingCancelled(String imageUri,
                            View view) {
                        // TODO Auto-generated method stub

                    }
    });

        return v;
    }

    @Override
    public View getInfoWindow(Marker marker) {
        // TODO Auto-generated method stub
        return null;
    }

}

I have 2 problems with this:

As we know the InfoWindow is drawn and later changes to it (in my case the new BitMap on the ImageView) are not shown/ the InfoWindow is not being updated. How can I "notify" the InfoWindow to reload itself when the imageLoader has finished? When I put

marker.showInfoWindow()

into onLoadingComplete it created an infinite loop where the marker will pop up, start loading the image, pop itself up etc.

My second problem is that on a slow network connection (simulated with the 5000ms delay in the code), the ImageView in the InfoWindow will always display the last loaded image, no matter if that image belongs to that ImageWindow/ Marker.

Any suggestions on how to propperly implement this?

fweigl
  • 21,278
  • 20
  • 114
  • 205

3 Answers3

31

You should be doing Marker.showInfoWindow() on marker that is currently showing info window when you receive model update.

So you need to do 3 things:

  1. create model and not put all the downloading into InfoWindowAdapter
  2. save reference to Marker (call it markerShowingInfoWindow)
    from getInfoContents(Marker marker)
  3. when model notifies you of download complete call
if (markerShowingInfoWindow != null && markerShowingInfoWindow.isInfoWindowShown()) {
    markerShowingInfoWindow.showInfoWindow();
}
MaciejGórski
  • 22,187
  • 7
  • 70
  • 94
  • 1
    Can anyone please put the code if anyone have solved the issue? – Nishant Shah Apr 22 '13 at 09:16
  • 17
    Programming is not about doing a copy-paste operation. My answer should be easy to follow and if it is not, you may ask a question to clarify things. – MaciejGórski Apr 30 '13 at 09:36
  • If the user clicks another marker before onLoadingComplete, won't the wrong infoWindow receive that download? – Ejmedina May 20 '13 at 18:09
  • 1
    @Ejmedina info window doesn't receive downloads. In my architecture proposition model stores image, notifies view controller (activity / fragment), which checks if currently shown info window should be updated: when downloaded image is associated with model object for which info window is displayed. – MaciejGórski May 20 '13 at 18:22
  • Thank @MaciejGórski for your clarification. I'll try to follow your proposition. How should the model notify the view? Have you implemented this? – Ejmedina May 21 '13 at 13:41
  • In the simplest form you can use Observer pattern. You can also use broadcasts (see [LocalBroadcastManager](http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html)) or event bus (e.g. [Otto from Square](https://github.com/square/otto)). Yes, I did. – MaciejGórski May 21 '13 at 13:52
  • @MaciejGórski thanks, it works! I used EventBus (from greenrobot). – pawegio Jan 22 '14 at 23:55
  • 1
    @MaciejGórski hey thanks.. i think the method got changed..markerShowingInfoWindow.isInfoWindowShown().. works for me.. – shyam.y Jan 18 '15 at 06:06
  • @sham.y Nice catch after almost 2 years. I was probably typing this from my head and without looking at the documentation. The method name could not change. I fixed it, thanks. – MaciejGórski Jan 20 '15 at 01:04
  • If I only do as the answer, the infinite loop problem is still there ! I have to add a cache of type HashMap, so everytime I need to load image, I will check whether the image already loaded, that how I solve the infinite calling getInfoContents() problem. Or did I misunderstand something ? – hungson175 Jul 12 '16 at 15:28
5

I did something similar. This was still giving me the recession error

if (markerShowingInfoWindow != null && markerShowingInfoWindow.isShowingInfoWindow()) {
    markerShowingInfoWindow.showInfoWindow();
}

So what i did was simply closes the window and open it again

if (markerShowingInfoWindow != null && markerShowingInfoWindow.isShowingInfoWindow()) {

    markerShowingInfoWindow.hideInfoWindow();
    markerShowingInfoWindow.showInfoWindow();

}

for a better detail version of the same answer here is my original soultion LINK

Community
  • 1
  • 1
James Nicholson
  • 987
  • 10
  • 20
  • This looks more like a comment to the accepted answer. If you really need to do this, then it seems to be a bug in Google Maps Android API v2. I have never encountered this bug tho and had no problems without using hide... – MaciejGórski Jan 20 '15 at 01:13
  • 1
    Simply calling .showInfoWindow again worked for me! Thanks for the idea – Denny Nov 26 '16 at 20:16
1

I was also faced same situation and solved using the following code.

In my adapter I have added public variable

public class MarkerInfoWindowAdapter implements GoogleMap.InfoWindowAdapter {

    public String ShopName="";   

    -------
    -------

     @Override
    public View getInfoWindow(Marker arg0) {

         View v;
         v = mInflater.inflate(R.layout.info_window, null);

         TextView shop= (TextView) v.findViewById(R.id.tv_shop);

         shop.setText(ShopName);


    }
}

and added MarkerClickListener in my main activity

----

MarkerInfoWindowAdapter mMarkerInfoWindowAdapter;

----
----

@Override
public void onMapReady(GoogleMap googleMap) {


    mMarkerInfoWindowAdapter = new MarkerInfoWindowAdapter(getApplicationContext());



    mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {

        @Override
        public boolean onMarkerClick(final Marker arg0) {

            mMarkerInfoWindowAdapter.ShopName= "my dynamic text";

            arg0.showInfoWindow();

            return true;
        }
    }

    mMap.setInfoWindowAdapter(mMarkerInfoWindowAdapter);


}
Bikesh M
  • 8,163
  • 6
  • 40
  • 52