it-swarm.com.de

Bitmap aus Vektor zeichnen

In meiner Anwendung muss ich ein großes Symbol für eine Benachrichtigung setzen . LargeIcon muss eine Bitmap sein, und meine Drawables sind Vektorbilder (die neue Funktion in Android, siehe diesen Link ) Das Problem Wenn ich versuche, eine Ressource, die ein Vektorbild ist, zu entschlüsseln, wird eine Null zurückgegeben.

Hier ist das Codebeispiel:

if (BitmapFactory.decodeResource(arg0.getResources(), R.drawable.vector_menu_objectifs) == null)
        Log.d("ISNULL", "NULL");
    else
        Log.d("ISNULL", "NOT NULL");

Wenn ich in diesem Beispiel R.drawable.vector_menu_objectifs durch ein "normales" Bild, ein png für ein Beispiel, ersetze, ist das Ergebnis nicht null (ich bekomme die richtige Bitmap).

87
liltof

Auf API überprüft: 17, 21, 23

public static Bitmap getBitmapFromVectorDrawable(Context context, int drawableId) {
    Drawable drawable = ContextCompat.getDrawable(context, drawableId);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        drawable = (DrawableCompat.wrap(drawable)).mutate();
    }

    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
            drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);

    return bitmap;
}

UPDATE:

Projektabschluss:

dependencies {
        classpath 'com.Android.tools.build:gradle:2.2.0-alpha5'
    }

Modulgrad:

Android {
    compileSdkVersion 23
    buildToolsVersion '23.0.3'
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 23
        vectorDrawables.useSupportLibrary = true
    }
    ...
}
...
154
Alexey

Sie können die folgende Methode verwenden:

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

was ich manchmal kombiniere mit:

private static Bitmap getBitmap(Context context, int drawableId) {
    Drawable drawable = ContextCompat.getDrawable(context, drawableId);
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable) drawable).getBitmap();
    } else if (drawable instanceof VectorDrawable) {
        return getBitmap((VectorDrawable) drawable);
    } else {
        throw new IllegalArgumentException("unsupported drawable type");
    }
}
57
snodnipper

Basierend auf den vorherigen Antworten kann es auf diese Weise vereinfacht werden, um sowohl VectorDrawable als auch BitmapDrawable abzugleichen und mit mindestens API 15 kompatibel zu sein.

public static Bitmap getBitmapFromDrawable(Context context, @DrawableRes int drawableId) {
    Drawable drawable = AppCompatResources.getDrawable(context, drawableId);

    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable) drawable).getBitmap();
    } else if (drawable instanceof VectorDrawableCompat || drawable instanceof VectorDrawable) {
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    } else {
        throw new IllegalArgumentException("unsupported drawable type");
    }
}

Dann müssen Sie Ihre Gradle-Datei hinzufügen:

Android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

Bei Pre-Lollipop wird VectorDrawableCompat und bei Lollipop VectorDrawable verwendet.

BEARBEITEN

Ich habe die Bedingung nach dem Kommentar von @ user3109468 bearbeitet

21
Eselfar

Wenn Sie bereit sind, Android KTX für Kotlin zu verwenden, können Sie die Erweiterungsmethode Drawable#toBitmap() verwenden, um denselben Effekt wie die anderen Antworten zu erzielen:

val bitmap = AppCompatResources.getDrawable(requireContext(), drawableId).toBitmap() 

oder 

val bitmap = AppCompatResources.getDrawable(context, drawableId).toBitmap() 

Um diese und weitere nützliche Erweiterungsmethoden hinzuzufügen, müssen Sie Folgendes auf Modulebene hinzufügen build.gradle 

repositories {
    google()
}

dependencies {
    implementation 'androidx.core:core-ktx:1.0.0-alpha1'
}

Link zur Quelle der Erweiterungsmethode hier .

Beachten Sie, dass dies für any Unterklasse von Drawable funktioniert. Wenn Drawable eine BitmapDrawable ist, wird die Verknüpfung zur Verwendung der zugrunde liegenden Bitmap hergestellt.

9
David Rawson

Ein dickes Lob an @Alexey

Hier ist die Kotlin-Version mit Erweiterungen zu Context

fun Context.getBitmapFromVectorDrawable(drawableId: Int): Bitmap? {
    var drawable = ContextCompat.getDrawable(this, drawableId) ?: return null

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        drawable = DrawableCompat.wrap(drawable).mutate()
    }

    val bitmap = Bitmap.createBitmap(
            drawable.intrinsicWidth,
            drawable.intrinsicHeight,
            Bitmap.Config.ARGB_8888) ?: return null
    val canvas = Canvas(bitmap)
    drawable.setBounds(0, 0, canvas.width, canvas.height)
    drawable.draw(canvas)

    return bitmap
}

Beispiel für die Verwendung in Activity:

val bitmap = this.getBitmapFromVectorDrawable(R.drawable.ic_done_white_24dp)
3
Gunhan

Getestet auf API 16 - JellyBean mit Vector Drawables

public static Bitmap getBitmapFromVectorDrawable(Context context, int drawableId) {
    Drawable drawable = AppCompatResources.getDrawable(context, drawableId);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        drawable = (DrawableCompat.wrap(drawable)).mutate();
    }

    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
            drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);

    return bitmap;

Dank an alle !

0
tomasmark79
Drawable layerDrawable = (Drawable) imageBase.getDrawable();
Bitmap bitmap = Bitmap.createBitmap(layerDrawable.getIntrinsicWidth(),
        layerDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
layerDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
layerDrawable.draw(canvas);

imageTeste.setImageBitmap (addGradient (Bitmap));

0
Amine

Wenn Ihr vector-Bild intrinsicWidth und intrinsicHeight klein ist und Sie versuchen, die Bitmap in einer großen Ansicht anzuzeigen, wird das Ergebnis verschwommen sein.

In diesem Fall können Sie eine neue Breite/Höhe für Ihre Bitmap angeben, um ein besseres Bild zu erhalten (oder Sie können die Vektorgröße in xml erhöhen, aber desireWidth und desireHeight können flexibler sein).

private fun getBitmap(drawableId: Int, desireWidth: Int? = null, desireHeight: Int? = null): Bitmap? {
    val drawable = AppCompatResources.getDrawable(context, drawableId) ?: return null
    val bitmap = Bitmap.createBitmap(
        desireWidth ?: drawable.intrinsicWidth,
        desireHeight ?: drawable.intrinsicHeight,
        Bitmap.Config.ARGB_8888
    )
    val canvas = Canvas(bitmap)
    drawable.setBounds(0, 0, canvas.width, canvas.height)
    drawable.draw(canvas)
    return bitmap
}

Ich hoffe es hilft

0
Linh

Wenn Sie Ihre Ausgabe auf eine gewünschte Ausgabegröße skalieren möchten, versuchen Sie Folgendes:

fun getBitmapFromVectorDrawable(context: Context, drawableId: Int, outputSize: OutputSize? = null): Bitmap? {
    var drawable = ContextCompat.getDrawable(context, drawableId) ?: return null
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        drawable = DrawableCompat.wrap(drawable).mutate()
    }

    var targetBitmap: Bitmap
    if (outputSize != null) {
        targetBitmap = Bitmap.createBitmap(outputSize.width,
                outputSize.height, Bitmap.Config.ARGB_8888)
    } else {
        targetBitmap = Bitmap.createBitmap(drawable.intrinsicWidth,
            drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
    }

    val canvas = Canvas(targetBitmap)
    val scaleX =  targetBitmap.width.toFloat()/drawable.intrinsicWidth.toFloat()
    val scaleY =  targetBitmap.height.toFloat()/drawable.intrinsicHeight.toFloat()
    canvas.scale(scaleX, scaleY)
    drawable.draw(canvas)

    return targetBitmap
}

class OutputSize(val width: Int, val height: Int)
0
Hans