android - vectoriales - que es una imagen vectorial
Obteniendo mapa de bits del vector dibujable (8)
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;
}
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
}
...
}
...
En mi aplicación, tengo que establecer un ícono grande para una notificación. LargeIcon debe ser un mapa de bits, y mis dibujos son imágenes vectoriales (la nueva característica en Android, vea este enlace ) El problema es que cuando intento decodificar un recurso que es una imagen vectorial, me devuelve un valor nulo.
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 este ejemplo, cuando reemplazo R.drawable.vector_menu_objectifs con una imagen "normal", un png por ejemplo, el resultado no es nulo (obtengo el mapa de bits correcto) ¿Hay algo que me falta?
En base a 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 debe agregar su 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
Felicitaciones a @Alexey
Aquí está la versión de
Kotlin
usa 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 la
Activity
:
val bitmap = this.getBitmapFromVectorDrawable(R.drawable.ic_done_white_24dp)
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");
}
}
Si desea poder escalar su salida al tamaño de salida deseado, pruebe el siguiente fragmento:
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)
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''
}
Tenga en cuenta que esto funcionará para
cualquier
subclase de
Drawable
y si el
Drawable
es un
BitmapDrawable
, será un atajo para usar el
Bitmap
subyacente.
Si su imagen
vector
intrinsicWidth
e
intrinsicHeight
es pequeña e intenta mostrar el mapa de bits en una vista grande, verá que el resultado es borroso.
En ese caso, puede proporcionar un nuevo ancho / alto para su mapa de bits para obtener la mejor imagen (o puede aumentar el tamaño del vector en xml, pero proporcionar el
desireWidth
y la
desireWidth
desireHeight
pueden ser más flexibles).
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
}
Espero que ayude
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));