Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using an xml Layout for a Google Map Marker for Android

I want to use a layout and not a drawable for my marker I am using with Google Maps Api 2 for an Android app.

Like this:

  Marker m = googleMap
                        .addMarker(new MarkerOptions()
                                .position(LOC)
                                .snippet(user)
                                .title(name)
                                .icon(BitmapDescriptorFactory.fromResource(R.layout.map_marker)));

However, it seems this is only designed for use from drawable folder.

I simply what an image with a background where I can change colors based on marker type. This is the layout I want to use:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:background="#222"
    android:id="@+id/llMarker">

    <ImageView
        android:id="@+id/ivMarker"
        android:layout_marginTop="5dp"
        android:layout_width="40dp"
        android:layout_height="40dp" />

</LinearLayout>

Pretty basic. How can I use this as a marker? (or at least replicate the end result that I am going for?)

The documents say you can use this:

fromResource (int resourceId)

So I assumed a layout might work.

UPDATE:

I have taken the concept from answer below and reworked some things; this still is not working; no errors. Just will not show image.

        LayoutInflater inflater = (LayoutInflater) getActivity()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = inflater.inflate(R.layout.map_marker, null);

        m = googleMap
                .addMarker(new MarkerOptions()
                        .position(LOC)
                        .snippet(user)
                        .title(name)
                        .icon(BitmapDescriptorFactory.fromBitmap(loadBitmapFromView(v))));

// method

  public static Bitmap loadBitmapFromView(View v) {

        if (v.getMeasuredHeight() <= 0) {
            v.measure(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
            Bitmap b = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
            Canvas c = new Canvas(b);
            v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
            v.draw(c);
            return b;
        }
        return null;
    }
like image 463
TheLettuceMaster Avatar asked Jul 12 '14 20:07

TheLettuceMaster


4 Answers

You cannot directly use a layout with BitmapDescriptorFactory.fromResource():

Creates a BitmapDescriptor using the resource id of an image.

However, you could draw the layout into a bitmap, and then use that. You'd need to:

  • Inflate the layout from xml (with a LayoutInflater).
  • Change whatever properties you want (e.g. background color).
  • Render this layout into a Bitmap, via Canvas, for example as described here.
  • Pass this bitmap into BitmapDescriptorFactory.fromBitmap().
like image 145
matiash Avatar answered Oct 24 '22 05:10

matiash


The following worked for me:

public static MarkerOptions createMarker(Context context, LatLng point, int bedroomCount) {
    MarkerOptions marker = new MarkerOptions();
    marker.position(point);
    int px = context.getResources().getDimensionPixelSize(R.dimen.map_marker_diameter);
    View markerView = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.map_circle_text, null);
    markerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    markerView.layout(0, 0, px, px);
    markerView.buildDrawingCache();
    TextView bedNumberTextView = (TextView)markerView.findViewById(R.id.bed_num_text_view);
    Bitmap mDotMarkerBitmap = Bitmap.createBitmap(px, px, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(mDotMarkerBitmap);
    bedNumberTextView.setText(bedroomCount);
    markerView.draw(canvas);
    marker.icon(BitmapDescriptorFactory.fromBitmap(mDotMarkerBitmap));
    return marker;
}

map_circle_text.xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/bed_num_text_view"
    android:gravity="center"
    android:layout_width="@dimen/map_marker_diameter"
    android:layout_height="@dimen/map_marker_diameter"
    android:background="@drawable/map_circle_pin"
    tools:text="4+"
    android:textColor="@color/white">
</TextView>

map_circle_pin.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <solid
        android:color="#666666"/>

    <size
        android:width="@dimen/map_marker_diameter"
        android:height="@dimen/map_marker_diameter"/>
</shape>
like image 39
Adam Johns Avatar answered Oct 24 '22 05:10

Adam Johns


Make a layout for your custom marker:

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/marker_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        tools:src="@drawable/ic_marker_selected" />

    <TextView
        android:id="@+id/marker_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textColor="#fff"
        android:textSize="14sp"
        tools:text="A" />

</merge>

Create your own MarkerView like this:

private class CustomMarkerView(root: ViewGroup,
                               text: String?,
                               isSelected: Boolean) : FrameLayout(root.context) {
    private var mImage: ImageView
    private var mTitle: TextView

    init {
        View.inflate(context, R.layout.marker_layout, this)
        mImage = findViewById(R.id.marker_image)
        mTitle = findViewById(R.id.marker_title)
        measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
        mTitle.text = text
        if (isSelected) {
            mImage.setImageResource(R.drawable.ic_marker_selected)
        } else {
            mImage.setImageResource(R.drawable.ic_marker_not_selected)
        }
    }
}

Now, you would need to get a BitmapDescriptor out of this custom view:

fun getMarkerIcon(root: ViewGroup, text: String?, isSelected: Boolean): BitmapDescriptor? {
    val markerView = CustomMarkerView(root, text, isSelected)
    markerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
    markerView.layout(0, 0, markerView.measuredWidth, markerView.measuredHeight)
    markerView.isDrawingCacheEnabled = true
    markerView.invalidate()
    markerView.buildDrawingCache(false)
    return BitmapDescriptorFactory.fromBitmap(markerView.drawingCache)
}

Then finally, you can apply it on your marker like this:

fun addMarkerOnMaps() {
    val markerIcon = getMarkerIcon(
            root = activity.findViewById(R.id.activity_content_container) as ViewGroup,
            text = markerName,
            isSelected = true)

    googleMap!!.addMarker(MarkerOptions()
            .position(LatLng(coordinates.latitude, coordinates.longitude))
            .icon(markerIcon))
}
like image 3
div Avatar answered Oct 24 '22 05:10

div


I also had this problem and this worked for me

    public static Bitmap createDrawableFromView(Context context, View view) {
    DisplayMetrics displayMetrics = new DisplayMetrics();
    ((Activity) context).getWindowManager().getDefaultDisplay()
            .getMetrics(displayMetrics);
    view.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
            LayoutParams.WRAP_CONTENT));
    view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
    view.layout(0, 0, displayMetrics.widthPixels,
            displayMetrics.heightPixels);
    view.buildDrawingCache();
    Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(),
            view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(bitmap);
    view.draw(canvas);
    return bitmap;

}
like image 1
YoShade Avatar answered Oct 24 '22 04:10

YoShade