Problem loading Picasso image in GoogleMap.InfoWindowAdapter

I am using Google Maps Api and want to show the image inside InfoWindow when the marker is clicked. I implemented it, but there is a problem with Picasso. When I click the marker, an info window is displayed, and ImageView shows the placeholder image. If I click one marker again, Picasso will successfully upload the image. I have to double click, it's so weird.

Screenshots for a better understanding:

First click the marker:

First click

When I click again:

Click again

Below are my codes:

InfoWindowAdapter (download Picasso here)

mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() { @Override public View getInfoWindow(Marker marker) { return null; } @Override public View getInfoContents(Marker marker) { View myContentsView = getLayoutInflater().inflate(R.layout.map_info_content, null); ImageView imageView = (ImageView) myContentsView.findViewById(R.id.imgView_map_info_content); Picasso.with(MainActivity.this) .load(marker.getSnippet()) .placeholder(R.drawable.ic_placeholder) .into(imageView); return myContentsView; } }); 

Setting markers (using snippet to pass image URL)

 for (MediaFeedData item : mItemList) { LatLng position = new LatLng(item.getLocation().getLatitude(), item.getLocation().getLongitude()); mMap.addMarker(new MarkerOptions() .snippet(item.getImages().getLowResolution().getImageUrl()) .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_point)) .position(position)); } 

InfoWindow xml layout

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:id="@+id/imgView_map_info_content" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> 
+7
android google-maps-android-api-2 picasso google-maps-markers
source share
2 answers

I solved it. In fact, this post is the answer. But I want to explain how to do this and give more detailed information to solve this problem in my situation.

When InfoWindow is displayed, it is fixed in the layout. This means that InfoWindows are not dynamic, it is just a photograph, a snapshot. Therefore, we need to update InfoWindow after successfully loading the image. We can use the Picasso callback for this.

I changed my codes as shown below:

My new InfoWindowAdapter class:

 public class MapInfoWindowAdapter implements GoogleMap.InfoWindowAdapter { private final Hashtable<String, Boolean> markerSet; private Context context; private View myContentsView; public MapInfoWindowAdapter(Context context, Hashtable<String, Boolean> markerSet) { this.context = context; this.markerSet = markerSet; } @Override public View getInfoWindow(Marker marker) { return null; } @Override public View getInfoContents(Marker marker) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); myContentsView = inflater.inflate(R.layout.map_info_content, null); ImageView imageView = (ImageView) myContentsView.findViewById(R.id.imgView_map_info_content); boolean isImageLoaded = markerSet.get(marker.getId()); if (isImageLoaded) { Picasso.with(context) .load(marker.getSnippet()) .placeholder(R.drawable.ic_placeholder) .into(imageView); } else { isImageLoaded = true; markerSet.put(marker.getId(), isImageLoaded); Picasso.with(context) .load(marker.getSnippet()) .placeholder(R.drawable.ic_placeholder) .into(imageView, new InfoWindowRefresher(marker)); } return myContentsView; } } 

I gave him a set of markers, it contains marker identifiers and a boolean to determine the image for this marker, loaded or not. I check this to choose which Picasso code should run. If I do not, it will be a recursion.

InfoWindowRefresher:

 public class InfoWindowRefresher implements Callback { private Marker markerToRefresh; public InfoWindowRefresher(Marker markerToRefresh) { this.markerToRefresh = markerToRefresh; } @Override public void onSuccess() { markerToRefresh.showInfoWindow(); } @Override public void onError() {} } 

Setting markers (using a snippet to pass the image URL):

 Hashtable<String, Boolean> markerSet = new Hashtable<>(); for (MediaFeedData item : mItemList) { LatLng position = new LatLng(item.getLocation().getLatitude(), item.getLocation().getLongitude()); MarkerOptions markerOptions = new MarkerOptions() .snippet(item.getImages().getLowResolution().getImageUrl()) .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_point)) .position(position); Marker marker = mMap.addMarker(markerOptions); markerSet.put(marker.getId(), false); } mMap.setInfoWindowAdapter(new MapInfoWindowAdapter(this, markerSet)); 
+8
source share

What works for me:

Inside getInfoWindow (marker token):

 Picasso.with(getActivity()) .load(URL) .error(R.drawable.my_loader) .placeholder(R.drawable.my_loader) .into(userPhoto, new MarkerCallback(marker,URL,userPhoto)); 

Then create a class:

 public class MarkerCallback implements Callback { Marker marker=null; String URL; ImageView userPhoto; MarkerCallback(Marker marker, String URL, ImageView userPhoto) { this.marker=marker; this.URL = URL; this.userPhoto = userPhoto; } @Override public void onError() { //Log.e(getClass().getSimpleName(), "Error loading thumbnail!"); } @Override public void onSuccess() { if (marker != null && marker.isInfoWindowShown()) { marker.hideInfoWindow(); Picasso.with(getActivity()) .load(URL) .into(userPhoto); marker.showInfoWindow(); } } 

}

+3
source share

All Articles