En mi aplicación, tengo que configurar un icono grande para una notificación. LargeIcon debe ser un bitmap, y mis dibujables son imágenes vectoriales (la nueva función en Android, consulte este enlace ). El problema es que cuando bash decodificar un recurso que es una imagen vectorial, obtengo un nulo devuelto.
Aquí está la muestra de código:
if (BitmapFactory.decodeResource(arg0.getResources(), R.drawable.vector_menu_objectifs) == null) Log.d("ISNULL", "NULL"); else Log.d("ISNULL", "NOT NULL");
En esta muestra, cuando reemplazo R.drawable.vector_menu_objectifs con una imagen “normal”, png por ejemplo, el resultado no es nulo (obtengo el bitmap correcto) ¿Hay algo que me falta?
Checked on API: 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; }
ACTUALIZAR:
Proyecto gradle:
dependencies { classpath 'com.android.tools.build:gradle:2.2.0-alpha5' }
Módulo gradle:
android { compileSdkVersion 23 buildToolsVersion '23.0.3' defaultConfig { minSdkVersion 16 targetSdkVersion 23 vectorDrawables.useSupportLibrary = true } ... } ...
Puedes usar el siguiente método:
@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; }
que a veces combino con:
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"); } }
En función de las respuestas anteriores, se puede simplificar así para que coincida tanto con VectorDrawable como con BitmapDrawable y sea compatible al menos con API 15.
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"); } }
Luego tienes que agregar en tu archivo gradle:
android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
En pre-Lollipop usará VectorDrawableCompat y en Lollipop usará VectorDrawable.
He editado la condición siguiendo el comentario de @ user3109468
Felicitaciones a @Alexey
Aquí está la versión de Kotlin
usa extensiones al 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 }
Ejemplo de uso en la Activity
:
val bitmap = this.getBitmapFromVectorDrawable(R.drawable.ic_done_white_24dp)
Si está dispuesto a usar Android KTX para Kotlin, puede usar el método de extensión Drawable#toBitmap()
para lograr el mismo efecto que las otras respuestas:
val bitmap = AppCompatResources.getDrawable(requireContext(), drawableId).toBitmap()
o
val bitmap = AppCompatResources.getDrawable(context, drawableId).toBitmap()
Para agregar este y otros métodos de extensión útiles, deberá agregar lo siguiente a su build.gradle
nivel de build.gradle
repositories { google() } dependencies { implementation 'androidx.core:core-ktx:1.0.0-alpha1' }
Enlace a la fuente del método de extensión aquí .
Tenga en cuenta que esto funcionará para cualquier subclase de Drawable
y si el Drawable
es un BitmapDrawable
de Drawable
de Drawable
BitmapDrawable
para utilizar el Bitmap
subyacente.
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));