Custom Marker icon using layout in Android.
Recently I was working on an app where I need to draw markers with images of users on the map I googled it and found some solutions and almost all of these solutions are using canvas to draw that kind of custom markers.I was thinking there must be an easier way to do it like converting a layout into the marker and add it to the map. So, in this post, I will show you how to do that.
For creating a custom marker create a layout file where we will describe how our custom marker will look like.
view_custom_marker.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_marker_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/marker_mask">
<ImageView
android:id="@+id/profile_image"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:contentDescription="@null"
android:src="@drawable/avatar" />
</FrameLayout>
First inflate the viw_custom_marker.xml
file.
mCustomMarkerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.view_custom_marker, null);
Now we will write a method which will take the mCustomMarkerView
and drawable resId
which you want to show on map and convert it into a bitmap.
/**
* @param view is custom marker layout which we will convert into bitmap.
* @param resId is the drawable which you want to show in marker.
* @return
*/
private Bitmap getMarkerBitmapFromView(View view, @DrawableRes int resId) {
mMarkerImageView.setImageResource(resId);
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.buildDrawingCache();
Bitmap returnedBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN);
Drawable drawable = view.getBackground();
if (drawable != null)
drawable.draw(canvas);
view.draw(canvas);
return returnedBitmap;
}
private void addCustomMarkerFromDrawable() {
if (mGoogleMap == null) {
return;
}
// adding a marker on map with image from drawable
mGoogleMap.addMarker(new MarkerOptions()
.position(mDummyLatLng)
.icon(BitmapDescriptorFactory.fromBitmap(getMarkerBitmapFromView(mCustomMarkerView,R.drawable.avatar))));
}
I am sure you guys must have a question in your mind what if I want to load an image from the server using URL
and show it on the map. For that, you can use the following code snippet which takes bitmap as an input parameter.
Note: For loading an image from url and converting it into a bitmap you can use Glide
, Picasso
.
/**
* @param view is custom marker layout which we will convert into bitmap.
* @param bitmap is the image which you want to show in marker.
* @return
*/
private Bitmap getMarkerBitmapFromView(View view, Bitmap bitmap) {
mMarkerImageView.setImageBitmap(bitmap);
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.buildDrawingCache();
Bitmap returnedBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN);
Drawable drawable = view.getBackground();
if (drawable != null)
drawable.draw(canvas);
view.draw(canvas);
return returnedBitmap;
}
private void addCustomMarkerFromURL() {
if (mGoogleMap == null) {
return;
}
// adding a marker with image from URL using glide image loading library
Glide.with(getApplicationContext())
.load(ImageUrl).asBitmap().fitCenter()
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) {
mGoogleMap.addMarker(new MarkerOptions().position(mDummyLatLng)
.icon(BitmapDescriptorFactory.fromBitmap(getMarkerBitmapFromView(mCustomMarkerView, bitmap))));
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(mDummyLatLng, 13f));
}
});
}
Now we just need to call the addCustomMarkerFromDrawable
or addCustomMarkerFromURL
in onMapReady
callback.
@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
MapsInitializer.initialize(this);
addCustomMarkerFromDrawable();
//addCustomMarkerFromURL();
}