10

I would like to use Picasso to retrieve the Bitmap image to use as a marker icon but I am not sure how to do so. If I am using Picasso to insert an image into an image view, I know I can use:

 Picasso.with(MainActivity.this).load(URL).into(photo_imageview);

Of course this will not work if I pass it to .icon()

Is there a simple way to achieve this?

Thanks to anyone taking a look at this!

iagreen
  • 31,470
  • 8
  • 76
  • 90
WeVie
  • 568
  • 2
  • 9
  • 25

3 Answers3

31

Picasso provides a generic Target interface you can use to implement your own image destination. Specifically, you will want to override onBitmapLoaded to populate your marker.

A basic implementation is given below.

public class PicassoMarker implements Target {
    Marker mMarker;

    PicassoMarker(Marker marker) {
        mMarker = marker;
    }

    @Override
    public int hashCode() {
        return mMarker.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        if(o instanceof PicassoMarker) {
            Marker marker = ((PicassoMarker) o).mMarker;
            return mMarker.equals(marker);
        } else {
            return false;
        }
    }

    @Override
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
        mMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
    }

    @Override
    public void onBitmapFailed(Drawable errorDrawable) {
    }

    @Override
    public void onPrepareLoad(Drawable placeHolderDrawable) {

    }
}

You would use it like this --

marker = new PicassoMarker(myMarker);
Picasso.with(MainActivity.this).load(URL).into(marker);

Note Picasso only holds a week reference to the Target passed to into. Therefore, the marker reference needs to exist until the image is loaded to avoid have the callbacks being cleaned up by the garbage collector.

iagreen
  • 31,470
  • 8
  • 76
  • 90
  • How does one do that? – WeVie Nov 23 '14 at 23:42
  • Hey @iagreen It show only default android marker not the image, please help me out for this. And onBitmapLoaded method not called. – Ankit Sharma Apr 09 '15 at 06:06
  • 1
    @AnkitSharma I would have to see your code to see what might be wrong. It is possible that the bitmap fails to load. The code above fails silently on failure. You can add logging to `onBitmapFailed` and see if the bitmap is actually being loaded. – iagreen Apr 09 '15 at 07:09
  • yes I log in onBitmapFailed but nothing display. And how can I show my code to you? – Ankit Sharma Apr 09 '15 at 07:33
  • Open a new question. Reference this question and say it isn't working. – iagreen Apr 09 '15 at 13:06
  • @AnkitSharma See the edit, it sounds like it might be your problem. If you are loading from a url and you used my original code there was a good chance the callbacks would be cleaned up prior to network call completing. – iagreen Apr 12 '15 at 04:02
  • somehow solved....that was my test app where I was trying to understand how it works, putting it into the app I'm actually developing make it work flawlessly – jack_the_beast Sep 25 '15 at 15:51
  • Awesome great solution – CROSP Feb 21 '16 at 12:21
  • Awesome great solution Thanks!! – Shridutt Kothari Aug 20 '16 at 10:32
  • @iagreen , i used your code and its working fine but there is small issue. Can you help me out. – Atula Sep 13 '16 at 15:07
0

Check this google maps sample code, you can find a InfoWindowAdapter implementation to achieve it : googlemaps/android-samples

S1ngoooor
  • 2,567
  • 2
  • 11
  • 13
0

As @iagreen answer for generating Icon from Bitmap, you can use Iconfactory.

Kotlin Version:

class PicassoMarker(
val marker: Marker,
private val iconFactory: IconFactory) : Target {
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
    Timber.d("picassoMarker onPrepareLoad : ")
}

override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {
    Timber.e("picassoMarker onBitmapFailed: ")
}

override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
    try {
        if (bitmap != null) {
            marker.icon = iconFactory.fromBitmap(bitmap)
        }
    } catch (ex: IllegalArgumentException) {
        Timber.e(ex, "Marker is dead")
    }
}

override fun equals(other: Any?): Boolean {
    if (other is PicassoMarker) {
        return marker == other
    }
    return false
}

override fun hashCode(): Int {
    return marker.hashCode()
}}

And use like this :

 fun addMarker(marker: Marker): com.mapbox.mapboxsdk.annotations.Marker {
    val markerOption = MarkerOptions().position(marker.latLng)

    markerOption.icon =
        iconFactory
            .fromBitmap(
                Bitmap.createBitmap(
                    1,
                    1,
                    Bitmap.Config.ARGB_8888
                )
            )

    val iconFactory = IconFactory.getInstance(context)

    val picassoMarker = PicassoMarker(
        mapProvider.map.addMarker(markerOption),
        iconFactory
    )

    try {
        val picasso = Picasso.get().apply {
            this.isLoggingEnabled = true
        }

        picasso.load(marker.iconUrl)
            .noPlaceholder()
            .into(picassoMarker)
    } catch (ex: Exception) {
        Timber.e(ex, "Picasso crashed")
    }

    return picassoMarker.marker
}
Sepehr
  • 960
  • 11
  • 17