How can we achieve a map marker icon with vector asset file, the way google shows it like this, programatically:
Update:
m
Might be a bit late to the game but this works great with Google Maps v2:
public static BitmapDescriptor getBitmapFromVector(@NonNull Context context,
@DrawableRes int vectorResourceId,
@ColorInt int tintColor) {
Drawable vectorDrawable = ResourcesCompat.getDrawable(
context.getResources(), vectorResourceId, null);
if (vectorDrawable == null) {
Log.e(TAG, "Requested vector resource was not found");
return BitmapDescriptorFactory.defaultMarker();
}
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
DrawableCompat.setTint(vectorDrawable, tintColor);
vectorDrawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
Initialized as:
locationMarkerIcon = LayoutUtils.getBitmapFromVector(ctx, R.drawable.ic_location_marker,
ContextCompat.getColor(ctx, R.color.marker_color));
Usage:
googleMap.addMarker(MarkerOptions().icon(getMarkerIcon()).position(latLng));
Note: getMarkerIcon()
just returns the initialized non null locationMarkerIcon
member variable.
Screenshot:
If someone who is looking for in kotlin here is the method for you :
private fun bitmapDescriptorFromVector(context: Context, vectorResId:Int):BitmapDescriptor {
var vectorDrawable = ContextCompat.getDrawable(context, vectorResId);
vectorDrawable!!.setBounds(0, 0, vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight());
var bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
var canvas = Canvas(bitmap);
vectorDrawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
above method will convert you vector icon to bitmapdescritor
map.addMarker(new MarkerOptions()
.position(latLng)
.icon(bitmapDescriptorFromVector(getActivity(), R.drawable.your_vector_asset))
.title(title)
and this one for setting marker for your map thanks for Leo Droidcoder from his answer only i have converted it to kotlin
In Kotlin: I used the below code to show the SVG image on Marker. Here, I used no background color / SVG.
fun getBitmapDescriptorFromVector(context: Context, @DrawableRes vectorDrawableResourceId: Int): BitmapDescriptor? {
val vectorDrawable = ContextCompat.getDrawable(context, vectorDrawableResourceId)
val bitmap = Bitmap.createBitmap(vectorDrawable!!.intrinsicWidth, vectorDrawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
vectorDrawable.setBounds(0, 0, canvas.width, canvas.height)
vectorDrawable.draw(canvas)
return BitmapDescriptorFactory.fromBitmap(bitmap)
}
Use like this way:
googleMap?.addMarker(MarkerOptions().position(LatLng(it.latitude!!, it.longitude!!))
.title(it.airLineDetails))?.setIcon(
getBitmapDescriptorFromVector(requireContext(), R.drawable.ic_flight_blue))
Screen Shot:
convert vector resource to bitmap object and use BitmapDescriptorFactory.fromBitmap(bitmap)
Bitmap bitmap = getBitmapFromVectorDrawable(getContext(),R.drawable.ic_pin);
BitmapDescriptor descriptor =BitmapDescriptorFactory.fromBitmap(bitmap);
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.icon(descriptor);
Bitmap converter:
public static Bitmap getBitmapFromVectorDrawable(Context context, int drawableId) {
Drawable drawable = AppCompatResources.getDrawable(context, drawableId)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
drawable = (DrawableCompat.wrap(drawable)).mutate();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
I was looking for exact same requirement, and seeing this question made me happy at first, but same as @Shuddh I wasn't happy with the given answers.
To make my story short, I am using following code for this requirement:
private BitmapDescriptor bitmapDescriptorFromVector(Context context, @DrawableRes int vectorDrawableResourceId) {
Drawable background = ContextCompat.getDrawable(context, R.drawable.ic_map_pin_filled_blue_48dp);
background.setBounds(0, 0, background.getIntrinsicWidth(), background.getIntrinsicHeight());
Drawable vectorDrawable = ContextCompat.getDrawable(context, vectorDrawableResourceId);
vectorDrawable.setBounds(40, 20, vectorDrawable.getIntrinsicWidth() + 40, vectorDrawable.getIntrinsicHeight() + 20);
Bitmap bitmap = Bitmap.createBitmap(background.getIntrinsicWidth(), background.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
background.draw(canvas);
vectorDrawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
and a usage example:
.icon(bitmapDescriptorFromVector(this, R.drawable.ic_car_white_24dp));
Note: you may wish to use different bounding for your vectors, my vectors were 24dp in size and I've used a 48dp png image(blue-part, which can be a vector too) as background.
UPDATE: Adding screenshot as it was requested.
You can use this method:
private BitmapDescriptor bitmapDescriptorFromVector(Context context, int vectorResId) {
Drawable vectorDrawable = ContextCompat.getDrawable(context, vectorResId);
vectorDrawable.setBounds(0, 0, vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight());
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
So your code will look like:
map.addMarker(new MarkerOptions()
.position(latLng)
.icon(bitmapDescriptorFromVector(getActivity(), R.drawable.your_vector_asset))
.title(title);
Edit:
In Kotlin it may look like:
private fun bitmapDescriptorFromVector(context: Context, vectorResId: Int): BitmapDescriptor? {
return ContextCompat.getDrawable(context, vectorResId)?.run {
setBounds(0, 0, intrinsicWidth, intrinsicHeight)
val bitmap = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888)
draw(Canvas(bitmap))
BitmapDescriptorFactory.fromBitmap(bitmap)
}
}