VectorDrawable with GoogleMap BitmapDescriptor

风流意气都作罢 提交于 2019-12-30 00:16:45

问题


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.


回答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);
}



回答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




回答3:


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");
    }
}
}



回答4:


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




回答5:


the same on Kotlin

private fun getBitmapDescriptorFromVector(id: Int, context: Context): BitmapDescriptor {
    var vectorDrawable: Drawable = context.getDrawable(id)
    var h = (24 * getResources().getDisplayMetrics().density).toInt();
    var w = (24 * getResources().getDisplayMetrics().density).toInt();
    vectorDrawable.setBounds(0, 0, w, h)
    var bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
    var canvas = Canvas(bm)
    vectorDrawable.draw(canvas)
    return BitmapDescriptorFactory.fromBitmap(bm)
}

EDIT @ CoolMind you are totally right, thanks - edited




回答6:


Kotlin Version

private fun getBitmapDescriptor(context: Context, id: Int): BitmapDescriptor? {
    val vectorDrawable: Drawable?
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        vectorDrawable = context.getDrawable(id)
    } else {
        vectorDrawable = ContextCompat.getDrawable(context, id)
    }
    if (vectorDrawable != null) {
        val w = vectorDrawable.intrinsicWidth
        val h = vectorDrawable.intrinsicHeight

        vectorDrawable.setBounds(0, 0, w, h)
        val bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        val canvas = Canvas(bm);
        vectorDrawable.draw(canvas);

        return BitmapDescriptorFactory.fromBitmap(bm);
    }
    return null
}


来源:https://stackoverflow.com/questions/33548447/vectordrawable-with-googlemap-bitmapdescriptor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!