Skip to content Skip to sidebar Skip to footer

How Can I Create A Speech-bubble Border For A Google Marker Custom Icon Using Picasso?

How can I use Picasso and Google Marker Custom Icon to achieve this feature? I know how to use Picasso for the image, but I don't know how to add that 'marker icon' on the bottom

Solution 1:

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;

publicclassBubbleTransformationimplementscom.squareup.picasso.Transformation {
    privatestaticfinalintouterMargin=40;
    privatefinalint margin;  // dp// margin is the board in dppublicBubbleTransformation(finalint margin) {
        this.margin = margin;
    }

    @Overridepublic Bitmap transform(final Bitmap source) {
        Bitmapoutput= Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
        Canvascanvas=newCanvas(output);

        PaintpaintBorder=newPaint();
        paintBorder.setColor(Color.CYAN);
        paintBorder.setStrokeWidth(margin);
        canvas.drawRoundRect(newRectF(outerMargin, outerMargin, source.getWidth() - outerMargin, source.getHeight() - outerMargin), 0, 0, paintBorder);

        PainttrianglePaint=newPaint(Paint.ANTI_ALIAS_FLAG);

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

        Pathtriangle=newPath();
        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);

        finalPaintpaint=newPaint();
        paint.setAntiAlias(true);
        paint.setShader(newBitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
        canvas.drawRoundRect(newRectF(margin+outerMargin, margin+outerMargin, source.getWidth() - (margin + outerMargin), source.getHeight() - (margin + outerMargin)), 0, 0, paint);

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

        return output;
    }

    @Overridepublic 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 = newTarget() {
    @OverridepublicvoidonBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
        Marker driver_marker = mMap.addMarker(newMarkerOptions()
                        .position(latLng)
                        .icon(BitmapDescriptorFactory.fromBitmap(bitmap))
                        .title("test")
                        .snippet("test address")
        );
    }

    @OverridepublicvoidonBitmapFailed(Drawable errorDrawable) {
        Log.d("picasso", "onBitmapFailed");
    }

    @OverridepublicvoidonPrepareLoad(Drawable placeHolderDrawable) {

    }
};

Result:

enter image description here

Solution 2:

You can set in kotlin like this..

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


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

    }


 privatefunaddCustomMarker() {
        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()))
        )
    }



    privatefungetMarkerBitmapFromView(): 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;

    }

Solution 3:

here marker view is your custom marker layout

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

    valbitmap= 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

privatefungetBitmapFromView(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
    }

Solution 4:

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

privatefuncreateDrawableFromView(): 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())
    ))

Post a Comment for "How Can I Create A Speech-bubble Border For A Google Marker Custom Icon Using Picasso?"