web-dev-qa-db-fra.com

VectorDrawable avec GoogleMap BitmapDescriptor

J'ai un problème avec Google Maps BitmapDescriptor lors de la création de l'icône pour MarkerOptions à l'aide de VectorDrawable, API 5.0+

Méthode utilisée pour la création:

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

Tout fonctionne très bien lorsque l'argument id contient un fichier png pouvant être dessiné. Toutefois, si je l'essaie avec VectorDrawable défini en xml, App plante toujours lorsque googleMap.addMarker(marker) (BitmapDescriptor n'est pas 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)

Peu importe la façon dont je récupère le dessin, nous avons essayé de créer une image bitmap en utilisant BitmapFactory.fromResources et plus tard BitmapDescritpionFactory.fromBitmap, mais les résultats sont les mêmes. Cela ne fonctionnera tout simplement pas avec le vecteur dessinable. J'ai essayé différents vecteurs également, mais il semble que la complexité du vecteur ne soit pas le problème ici.

Est-ce que quelqu'un sait comment résoudre ce crash?

@modifier

Il semble que le problème ne vienne pas de la variable BitmapDescriptior elle-même, mais plutôt du chargement de VectorDrawable qui renvoyait un bitmap incorrect. Cependant, la solution proposée en réponse est toujours valable.

25
Than

Solution possible: 

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);
}
37
Than

Selon le rapport de bogue ( posté par vaughandroid - merci!) Avec un VectorDrawable ne sera pas supporté pour le moment. Voir le commentaire dans le rapport de bogue pour plus d'informations.

Voici la solution suggérée par l'équipe de Google Maps:

/**
 * 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);
}

utilisé de cette façon:

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

La teinte du vecteur est un bonus

8
lbarbosa

Voici une autre référence: 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");
    }
}
}
6
TeeTracker

VectorDrawable à BitmapDescriptor sans teinte

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

Merci @lbarbosa

3
AndyW

la même chose sur 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)
}
0
kazimad