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