VectorDrawable with GoogleMap BitmapDescriptor

14,964

Solution 1

Possible workaround:

private BitmapDescriptor getBitmapDescriptor(int id) {
    Drawable vectorDrawable = context.getDrawable(id);
    int h = ((int) Utils.convertDpToPixel(42, context));
    int w = ((int) Utils.convertDpToPixel(25, context));
    vectorDrawable.setBounds(0, 0, w, h);
    Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bm);
    vectorDrawable.draw(canvas);
    return BitmapDescriptorFactory.fromBitmap(bm);
}

Solution 2

According to the bug report (posted by vaughandroid - thanks!) using a VectorDrawable won't be supported for the time being. See the comment in the bug report for more information.

Here's the suggested workaround from the Google Maps team:

/**
 * Demonstrates converting a {@link Drawable} to a {@link BitmapDescriptor},
 * for use as a marker icon.
 */
private BitmapDescriptor vectorToBitmap(@DrawableRes int id, @ColorInt int color) {
    Drawable vectorDrawable = ResourcesCompat.getDrawable(getResources(), id, null);
    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, color);
    vectorDrawable.draw(canvas);
    return BitmapDescriptorFactory.fromBitmap(bitmap);
}

used this way:

// Vector drawable resource as a marker icon.
    mMap.addMarker(new MarkerOptions()
            .position(ALICE_SPRINGS)
            .icon(vectorToBitmap(R.drawable.ic_android, Color.parseColor("#A4C639")))
            .title("Alice Springs"));

Tinting of the vector is a bonus

Solution 3

Or you could simply use Android KTX

e.g:

val markerBitmap = ResourcesCompat.getDrawable(resources, R.drawable.ic_marker, null)?.toBitmap()
val icon = BitmapDescriptorFactory.fromBitmap(markerBitmap)
val marker = MarkerOptions().icon(icon)

Reference: .toBitmap()

Solution 4

Here is another reference: http://qiita.com/konifar/items/aaff934edbf44e39b04a

public class ResourceUtil {

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static Bitmap getBitmap(VectorDrawable vectorDrawable) {
    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());
    vectorDrawable.draw(canvas);
    return bitmap;
}

private static Bitmap getBitmap(VectorDrawableCompat vectorDrawable) {
    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());
    vectorDrawable.draw(canvas);
    return bitmap;
}

public static Bitmap getBitmap(Context context, @DrawableRes int drawableResId) {
    Drawable drawable = ContextCompat.getDrawable(context, drawableResId);
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable) drawable).getBitmap();
    } else if (drawable instanceof VectorDrawableCompat) {
        return getBitmap((VectorDrawableCompat) drawable);
    } else if (drawable instanceof VectorDrawable) {
        return getBitmap((VectorDrawable) drawable);
    } else {
        throw new IllegalArgumentException("Unsupported drawable type");
    }
}
}

Solution 5

VectorDrawable to BitmapDescriptor without tint

private BitmapDescriptor getBitmapDescriptor(@DrawableRes int id) {
        Drawable vectorDrawable = ResourcesCompat.getDrawable(getResources(), id, null);
        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());
        vectorDrawable.draw(canvas);
        return BitmapDescriptorFactory.fromBitmap(bitmap);
    }

Thanks @lbarbosa

Share:
14,964
Than
Author by

Than

Android enthusiast, self learner, working as Android dev since late 2013. RxJava fan

Updated on June 03, 2022

Comments

  • Than
    Than about 2 years

    I have problem with google maps BitmapDescriptor while creating icon for MarkerOptions using VectorDrawable, API 5.0+

    Method used for creation:

    @NonNull
    private BitmapDescriptor getBitmapDescriptor(int id) {
        return BitmapDescriptorFactory.fromResource(id);
    }
    

    Everything works great when id argument contains png drawable, however if I try it with VectorDrawable defined in xml, App always crash when googleMap.addMarker(marker) (BitmapDescriptor is not null).

    11-05 10:15:05.213 14536-14536/xxx.xxxxx.app E/AndroidRuntime: FATAL EXCEPTION: main
        Process: xxx.xxxxx.app, PID: 14536
        java.lang.NullPointerException
            at com.google.a.a.ae.a(Unknown Source)
            at com.google.maps.api.android.lib6.d.dn.<init>(Unknown Source)
            at com.google.maps.api.android.lib6.d.dm.a(Unknown Source)
            at com.google.maps.api.android.lib6.d.ag.<init>(Unknown Source)
            at com.google.maps.api.android.lib6.d.eu.a(Unknown Source)
            at com.google.android.gms.maps.internal.j.onTransact(SourceFile:167)
            at android.os.Binder.transact(Binder.java:380)
            at com.google.android.gms.maps.internal.IGoogleMapDelegate$zza$zza.addMarker(Unknown Source)
            at com.google.android.gms.maps.GoogleMap.addMarker(Unknown Source)
            at xxx.xxxxx.app.ui.details.DetailActivity.lambda$initGoogleMaps$23(DetailActivity.java:387)
            at xxx.xxxxx.app.ui.details.DetailActivity.access$lambda$10(DetailActivity.java)
            at xxx.xxxxx.app.ui.details.DetailActivity$$Lambda$13.onMapReady(Unknown Source)
            at com.google.android.gms.maps.SupportMapFragment$zza$1.zza(Unknown Source)
            at com.google.android.gms.maps.internal.zzl$zza.onTransact(Unknown Source)
            at android.os.Binder.transact(Binder.java:380)
            at com.google.android.gms.maps.internal.av.a(SourceFile:82)
            at com.google.maps.api.android.lib6.d.fa.run(Unknown Source)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
    

    It doesn't matter how i retrieve drawable, tried creating bitmap using BitmapFactory.fromResources and later BitmapDescritpionFactory.fromBitmap but results are the same. It just won't work with vector drawable. Tried different vectors as well but it's seems that vector complexity is not the issue here.

    Does anyone know how to fix this crash?

    @edit

    It seems like the problem wasn't with the BitmapDescriptior itself, but rather with loading VectorDrawable which was returning incorrect bitmap. However solution proposed in answer is still fine.

  • Sam G-H
    Sam G-H over 8 years
    Rather than calculating the height and width, you can use VectorDrawable.getIntrinsicHeight/Width(). Unless you're actually trying to scale the graphics
  • Than
    Than over 8 years
    Actually I'm doing the scaling there, however it may be usefull for others
  • Pepster
    Pepster over 8 years
    In case you are < 21. Use Drawable vectorDrawable = ContextCompat.getDrawable(mContext, id); instead
  • CoolMind
    CoolMind about 5 years
    If for some reason you use nullable context, then why you write: context?.getDrawable(id)!!? It will crash with Kotlin NPE in case context == null.
  • imin
    imin almost 3 years
    how do we change the color/tint of the vector with this?
  • imin
    imin almost 3 years
    how do we change the color/tint of the vector with this?