Obtener mapa de bits del elemento de diseño vectorial
En mi aplicación, tengo que establecer un icono grande para una notificación. LargeIcon debe ser un mapa de bits, y mis elementos de diseño son imágenes vectoriales (la nueva característica en Android, ver este enlace) El problema es que cuando intento decodificar un recurso que es una imagen vectorial, obtengo un null 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 reemplace R. drawable.vector_menu_objectifs con una imagen "normal", un png por ejemplo, el resultado no es null (obtengo la correcta bits) ¿Hay algo que me estoy perdiendo?
6 answers
Comprobado en 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;
}
ACTUALIZACIÓN:
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
}
...
}
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-19 20:39:44
Puede utilizar 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");
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-11 19:14:18
Basado en las respuestas anteriores se puede simplificar así para que coincida con VectorDrawable y BitmapDrawable y para ser compatible con al menos 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.
EDITAR
He editado la condición siguiendo el comentario de @user3109468
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-27 16:34:01
Felicitaciones a @Alexey
Aquí está la versión Kotlin
usando extensiones para 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 Activity
:
val bitmap = this.getBitmapFromVectorDrawable(R.drawable.ic_done_white_24dp)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-18 14:52:00
Si estás dispuesto a usar Android KTX para Kotlin puedes 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 nivel de módulo 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
lo hará acceso directo para usar el Bitmap
subyacente.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-08 08:35:52
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));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-03 13:28:50