Home » Android » How to get image in infoWindow on Google Maps with picasso – Android

How to get image in infoWindow on Google Maps with picasso – Android

Posted by: admin June 15, 2020 Leave a comment

Questions:

I have created an app that implements a MapsView. And when i click the marker, it will show me the info window where the data is retrieved from the database by using picasso. It works fine, but the problem is that the image in the info window not shows me the image that i needed, it still shows me the placeholder image. But when i click the map and click again to the marker, it will shows me the image that i needed. But if i’m not clicking on the map (still clicking the marker), it still always shows me the placeholder marker. How do I display the image that i needed (the placeholder image will replace with the image that i needed) with a time?

Here’s my code

public void plotMarkers(ArrayList<MyMarker> markers) {
    if(markers.size() > 0) {
        for (MyMarker myMarker : markers)
        {
            dest = new LatLng(myMarker.getmLatitude(), myMarker.getmLongitude());
            markerOption = new MarkerOptions().position(dest);
            location_marker = mMap.addMarker(markerOption);
            Target target = new PicassoMarker(location_marker);
            targets.add(target);

            ImageView image = new ImageView(this);
            image.setImageResource(R.mipmap.marker);
            int width = image.getDrawable().getIntrinsicWidth();
            int height = image.getDrawable().getIntrinsicHeight();

            Picasso.with(MapsActivity.this).load(myMarker.getmIcon()).resize(width, height).onlyScaleDown().into(target);
            mMarkersHashMap.put(location_marker, myMarker);

            i = getIntent();
            if(i.getBooleanExtra("maps", true)) {
                location_marker.setTitle(i.getStringExtra("nama"));
                mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(dest, 16));
            }
            else {
                mMap.setInfoWindowAdapter(new MarkerInfoWindowAdapter());
            }
        }
    }
}

public class MarkerInfoWindowAdapter implements GoogleMap.InfoWindowAdapter
{
    @Override
    public View getInfoWindow(Marker marker) {
        return null;
    }

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

        MyMarker myMarker = mMarkersHashMap.get(marker);

        TextView markerLabel = (TextView) v.findViewById(R.id.marker_label);
        markerLabel.setText(myMarker.getmLabel());

        ImageView foto = (ImageView) v.findViewById(R.id.foto);
        Picasso.with(getApplicationContext()).load(myMarker.getmImage()).placeholder(R.layout.progress).error(R.mipmap.error).into(foto);

        TextView anotherLabel = (TextView) v.findViewById(R.id.another_label);
        anotherLabel.setText("Baca selengkapnya...");

        return v;
    }
}
How to&Answers:

The info window is basically a bitmap, captured from the views that you populated. As a result, changes to those views — such as Picasso asynchronously updating an ImageView — will not update the info window.

One solution that works is to call showInfoWindow() on the Marker after Picasso has obtained and cached the image. For example, this sample app uses Picasso to populate info windows, and uses a Picasso Callback to call showInfoWindow():

/***
  Copyright (c) 2013-2014 CommonsWare, LLC
  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  use this file except in compliance with the License. You may obtain a copy
  of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
  by applicable law or agreed to in writing, software distributed under the
  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
  OF ANY KIND, either express or implied. See the License for the specific
  language governing permissions and limitations under the License.

  From _The Busy Coder's Guide to Android Development_
    https://commonsware.com/Android
 */

package com.commonsware.android.mapsv2.imagepopups;

import android.annotation.SuppressLint;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.HashMap;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.model.Marker;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;

class PopupAdapter implements InfoWindowAdapter {
  private View popup=null;
  private LayoutInflater inflater=null;
  private HashMap<String, Uri> images=null;
  private Context ctxt=null;
  private int iconWidth=-1;
  private int iconHeight=-1;
  private Marker lastMarker=null;

  PopupAdapter(Context ctxt, LayoutInflater inflater,
               HashMap<String, Uri> images) {
    this.ctxt=ctxt;
    this.inflater=inflater;
    this.images=images;

    iconWidth=
        ctxt.getResources().getDimensionPixelSize(R.dimen.icon_width);
    iconHeight=
        ctxt.getResources().getDimensionPixelSize(R.dimen.icon_height);
  }

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

  @SuppressLint("InflateParams")
  @Override
  public View getInfoContents(Marker marker) {
    if (popup == null) {
      popup=inflater.inflate(R.layout.popup, null);
    }

    if (lastMarker == null
        || !lastMarker.getId().equals(marker.getId())) {
      lastMarker=marker;

      TextView tv=(TextView)popup.findViewById(R.id.title);

      tv.setText(marker.getTitle());
      tv=(TextView)popup.findViewById(R.id.snippet);
      tv.setText(marker.getSnippet());

      Uri image=images.get(marker.getId());
      ImageView icon=(ImageView)popup.findViewById(R.id.icon);

      if (image == null) {
        icon.setVisibility(View.GONE);
      }
      else {
        Picasso.with(ctxt).load(image).resize(iconWidth, iconHeight)
               .centerCrop().noFade()
               .placeholder(R.drawable.placeholder)
               .into(icon, new MarkerCallback(marker));
      }
    }

    return(popup);
  }

  static class MarkerCallback implements Callback {
    Marker marker=null;

    MarkerCallback(Marker marker) {
      this.marker=marker;
    }

    @Override
    public void onError() {
      Log.e(getClass().getSimpleName(), "Error loading thumbnail!");
    }

    @Override
    public void onSuccess() {
      if (marker != null && marker.isInfoWindowShown()) {
        marker.showInfoWindow();
      }
    }
  }
}

Basically, if when Picasso gets the image, the info window is still open for the associated Marker, I call showInfoWindow(). The visual effect resembles normal Picasso behavior: a placeholder, followed by the real image replacing the placeholder.

Answer:

kotlin version

   Picasso.get()
            .load(it.avatar)
            .placeholder(R.drawable.ic_person_black_24dp)
            .error(R.drawable.ic_person_black_24dp)
            .into(avatarView, object : Callback {
                override fun onSuccess() {
                    if (marker != null && marker.isInfoWindowShown) {
                        marker.hideInfoWindow()
                        marker.showInfoWindow()
                    }
                }

                override fun onError(e: Exception?) {
                    Timber.e("Error loading avatar to info window!")
                }
            })