Получение растрового изображения из векторного чертежа
в моем приложении я должен установить большой значок для уведомления. LargeIcon должен быть растровым, а мои чертежи-векторными изображениями (новая функция в Android, см. этой ссылке) Проблема в том, что когда я пытаюсь декодировать ресурс, который является векторным изображением, я получаю возвращенное значение null.
вот пример кода :
if (BitmapFactory.decodeResource(arg0.getResources(), R.drawable.vector_menu_objectifs) == null)
Log.d("ISNULL", "NULL");
else
Log.d("ISNULL", "NOT NULL");
в этом примере, когда я заменяю R. drawable.vector_menu_objectifs с "нормальным" изображением, png для примера, результат не равен нулю (Я получаю правильное растровое изображение) Есть ли что-то, что я упускаю?
6 ответов:
проверено на 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; }
обновление:
проект gradle:
dependencies { classpath 'com.android.tools.build:gradle:2.2.0-alpha5' }
модуль gradle:
android { compileSdkVersion 23 buildToolsVersion '23.0.3' defaultConfig { minSdkVersion 16 targetSdkVersion 23 vectorDrawables.useSupportLibrary = true } ... } ...
Вы можете использовать следующий метод:
@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(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"); } }
основываясь на предыдущих ответах, его можно упростить, чтобы он соответствовал как VectorDrawable, так и BitmapDrawable и был совместим по крайней мере с 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"); } }
затем вы должны добавить в свой файл gradle:
android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
по предварительной Lollipop будет использовать VectorDrawableCompat и на чупа-чупс он будет использовать VectorDrawable.
EDIT
я отредактировал условие после комментария @user3109468
Слава @Alexey
здесь
Kotlin
версия с использованием расширений для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 }
пример использования
Activity
:val bitmap = this.getBitmapFromVectorDrawable(R.drawable.ic_done_white_24dp)
если вы готовы использовать Android KTX для Kotlin вы можете использовать метод расширения
Drawable#toBitmap()
для достижения того же эффекта, что и другие ответы:val bitmap = AppCompatResources.getDrawable(requireContext(), drawableId).toBitmap()
или
val bitmap = AppCompatResources.getDrawable(context, drawableId).toBitmap()
добавить и другие полезные методы расширения, вам нужно будет добавить следующий код в модуль-уровень
build.gradle
repositories { google() } dependencies { implementation 'androidx.core:core-ktx:1.0.0-alpha1' }
ссылка на источник метода расширения здесь.
обратите внимание, что это будет работать для любой подкласс
Drawable
и еслиDrawable
этоBitmapDrawable
это будет ярлык для использования базовыхBitmap
.
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));