11

How can I use Picasso and Google Marker Custom Icon to achieve this feature?

enter image description here

I know how to use Picasso for the image, but I don't know how to add that "marker icon" on the bottom and the borders.

Picasso.with(mContext)
            .load(url)
            .resize(250, 250)
            .centerInside()
            .into(new Target() {
                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    Marker driver_marker = mMap.addMarker(new MarkerOptions()
                            .position(new LatLng(Double.parseDouble(lat), Double.parseDouble(lng)))
                            .icon(BitmapDescriptorFactory.fromBitmap(bitmap))
                            .title(name)
                            .snippet(address)
                    );


                    @Override
                    public void onBitmapFailed (Drawable errorDrawable){
                    }

                    @Override
                    public void onPrepareLoad (Drawable placeHolderDrawable){
                    }
                });
            }

I added this inside the onBitmapLoaded:

Paint paint = new Paint();
    paint.setColor(Color.YELLOW);
    paint.setStrokeWidth(10);
    paint.setShadowLayer(5, 0, 1, Color.RED);

    Canvas canvas = new Canvas(bitmap);
    canvas.drawLine(0, 0, canvas.getWidth(), 0, paint);
    canvas.drawLine(0, 0, 0, canvas.getHeight(), paint);
    canvas.drawLine(0, canvas.getHeight(), canvas.getWidth(), canvas.getHeight(), paint);
    canvas.drawLine(canvas.getWidth(), 0, canvas.getWidth(), canvas.getHeight(), paint);

And that seems to added the borders, but how do I add that inverted pyramid with the Canvas? Thanks, after that, I'm pretty much done! :D

Hadi Note
  • 1,386
  • 17
  • 16
Raymond Seger
  • 1,080
  • 5
  • 17
  • 34
  • 1
    it wasn't answered there – Raymond Seger Jan 04 '16 at 08:12
  • 1
    at best, what i can get is i make a canvas from the bitmap, how do i then create the border with the canvas? – Raymond Seger Jan 04 '16 at 08:17
  • Create your own transform class that draws Paint objects to a Canvas. You could start with this: https://gist.github.com/aprock/6213395 – Daniel Nugent Jan 04 '16 at 08:29
  • Try to set anchor to driver_marker(Marker)`driver_marker.anchor(0.5f, 0.5f);` see [here](https://developers.google.com/android/reference/com/google/android/gms/maps/model/Marker.html#setAnchor%28float,%20float%29) – pRaNaY Jan 04 '16 at 08:33
  • 1
    well, i added canvas and Paint which seems to create the borders, now all i need is the inverted pyramid thing with the Canvas. I don't know how, haha. – Raymond Seger Jan 04 '16 at 08:35
  • I updated the question, so you can see which code i added for the Border – Raymond Seger Jan 04 '16 at 08:36

4 Answers4

15

Here is a transformation class that I got working. It's lacking the corner radius and any gradients, but it has the inverted pyramid on the bottom, and it should serve as a good starting point.

Here is the transformation class:

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;

public class BubbleTransformation implements com.squareup.picasso.Transformation {
    private static final int outerMargin = 40;
    private final int margin;  // dp

    // margin is the board in dp
    public BubbleTransformation(final int margin) {
        this.margin = margin;
    }

    @Override
    public Bitmap transform(final Bitmap source) {
        Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        Paint paintBorder = new Paint();
        paintBorder.setColor(Color.CYAN);
        paintBorder.setStrokeWidth(margin);
        canvas.drawRoundRect(new RectF(outerMargin, outerMargin, source.getWidth() - outerMargin, source.getHeight() - outerMargin), 0, 0, paintBorder);

        Paint trianglePaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        trianglePaint.setStrokeWidth(2);
        trianglePaint.setColor(Color.CYAN);
        trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        trianglePaint.setAntiAlias(true);

        Path triangle = new Path();
        triangle.setFillType(Path.FillType.EVEN_ODD);
        triangle.moveTo(outerMargin, source.getHeight() / 2);
        triangle.lineTo(source.getWidth()/2,source.getHeight());
        triangle.lineTo(source.getWidth()-outerMargin,source.getHeight()/2);
        triangle.close();

        canvas.drawPath(triangle, trianglePaint);

        final Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
        canvas.drawRoundRect(new RectF(margin+outerMargin, margin+outerMargin, source.getWidth() - (margin + outerMargin), source.getHeight() - (margin + outerMargin)), 0, 0, paint);

        if (source != output) {
            source.recycle();
        }

        return output;
    }

    @Override
    public String key() {
        return "rounded";
    }
}

The call to Picasso:

 Picasso.with(getActivity())
            .load(user_photo_url)
            .resize(250,250)
            .centerCrop()
            .transform(new BubbleTransformation(20))
            .into(mTarget);

The Target:

Target mTarget = new Target() {
    @Override
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
        Marker driver_marker = mMap.addMarker(new MarkerOptions()
                        .position(latLng)
                        .icon(BitmapDescriptorFactory.fromBitmap(bitmap))
                        .title("test")
                        .snippet("test address")
        );
    }

    @Override
    public void onBitmapFailed(Drawable errorDrawable) {
        Log.d("picasso", "onBitmapFailed");
    }

    @Override
    public void onPrepareLoad(Drawable placeHolderDrawable) {

    }
};

Result:

enter image description here

Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
2

You can set in kotlin like this..

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)


        mapView.getMapAsync { googleMap ->
            googleMap1 = googleMap as GoogleMap
            addCustomMarker()
        }

    }


 private fun addCustomMarker() {
        Log.d("addCustomMarker", "addCustomMarker()")
        if (googleMap1 == null) {
            return
        }
        // adding a marker on map with image from  drawable
        googleMap1.addMarker(
            MarkerOptions()
                .position(LatLng(23.0225 , 72.5714))
                .icon(BitmapDescriptorFactory.fromBitmap(getMarkerBitmapFromView()))
        )
    }



    private fun getMarkerBitmapFromView(): Bitmap? {
        val customMarkerView: View? = layoutInflater.inflate(R.layout.view_custom_marker, null)
//        val markerImageView: ImageView =
//            customMarkerView.findViewById<View>(R.id.profile_image) as ImageView
        customMarkerView?.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED );
        customMarkerView?.layout(0, 0, customMarkerView.measuredWidth, customMarkerView.measuredHeight);
        customMarkerView?.buildDrawingCache();
        val returnedBitmap = Bitmap.createBitmap(
            customMarkerView!!.measuredWidth, customMarkerView.measuredHeight,
            Bitmap.Config.ARGB_8888
        )
        val canvas = Canvas(returnedBitmap)
        canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN)
        val drawable = customMarkerView.background

        drawable?.draw(canvas);
        customMarkerView.draw(canvas);
        return returnedBitmap;

    }
Zealous System
  • 2,080
  • 11
  • 22
1

here marker view is your custom marker layout

    val view = LayoutInflater.from(context).inflate(R.layout.marker_view, 
    null,false)

    val bitmap = getBitmapFromView(view)

    // Uses a custom icon.
     mSydney = mMap.addMarker(MarkerOptions()
        .position(SYDNEY)
        .title("Sydney")
        .snippet("Population: 4,627,300")
        .icon(BitmapDescriptorFactory.fromResource(bitmap)))

use this function to convert bitmap from view

private fun getBitmapFromView(view: View): Bitmap {
        view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
        val bitmap = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight,
                Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        view.layout(0, 0, view.measuredWidth, view.measuredHeight)
        view.draw(canvas)
        return bitmap
    }
Vijay Makwana
  • 506
  • 5
  • 14
0

I am a bit late to the party but all the above solutions are either not working or deprecated.

If you want something similar to the image below then You just have to follow these 3 simple steps.

enter image description here

1. Create your XML layout which you want to be shown as marker

I have created custom_location_marker.xml layout.

2. Just copy and paste this function in your Map Fragment/ Map Activity

    private fun createDrawableFromView(): Bitmap {
    val customMarkerView: View = View.inflate(
        requireActivity(),
        R.layout.custom_location_marker, null
    )

    customMarkerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
    customMarkerView.layout(
        0,
        0,
        customMarkerView.measuredWidth,
        customMarkerView.measuredHeight
    )

    val bitmap =
        Bitmap.createBitmap(
            customMarkerView.width,
            customMarkerView.height,
            Bitmap.Config.ARGB_8888
        )
    val canvas = Canvas(bitmap)
    customMarkerView.draw(canvas)
    return bitmap
}

3. And then when the map is ready, just call this function to add marker in the map:

googleMap.addMarker(MarkerOptions().position(LatLng(24.0, 260.0)).icon(
        BitmapDescriptorFactory
            .fromBitmap(createDrawableFromView())
    ))
Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82