Подтвердить что ты не робот

VectorDrawable с GoogleMap BitmapDescriptor

У меня проблема с картами google BitmapDescriptor при создании значка для MarkerOptions с помощью VectorDrawable, API 5.0 +

Метод, используемый для создания:

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

Все отлично работает, когда аргумент id содержит png drawable, однако если я попробую его с VectorDrawable, определенным в xml, приложение всегда сбой, когда googleMap.addMarker(marker) (BitmapDescriptor не равно 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)

Не имеет значения, как я извлекаю drawable, попытался создать растровое изображение, используя BitmapFactory.fromResources и позже BitmapDescritpionFactory.fromBitmap, но результаты одинаковы. Он просто не будет работать с вектором. Пробовал и разные векторы, но, похоже, проблема с вектором не является проблемой.

Кто-нибудь знает, как исправить эту ошибку?

@edit

Похоже, проблема была не в самом BitmapDescriptior, а в загрузке VectorDrawable, которая возвращала неправильное растровое изображение. Однако решение, предлагаемое в ответ, по-прежнему прекрасное.

4b9b3361

Ответ 1

Возможное обходное решение:

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

Согласно отчет об ошибке (опубликованный vaughandroid - спасибо!), используя пока что VectorDrawable не будет поддерживаться. Дополнительную информацию см. В комментарии в отчете об ошибке.

Здесь предлагается обходное решение из команды 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);
}

используется следующим образом:

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

Тонирование вектора - это бонус

Ответ 3

Вот еще одна ссылка: 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 до BitmapDescriptor без оттенка

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

Спасибо @lbarbosa

Ответ 5

то же самое на 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)
}