在我的应用程序中,我必须为通知设置一个大图标。 LargeIcon必须是一个Bitmap,我的drawable是矢量图像(Android中的新功能,请参阅this link) 问题是,当我尝试解码作为矢量图像的资源时,我得到一个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为例,结果不为空(我得到正确的位图) 有什么我想念的吗?
答案 0 :(得分:174)
检查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;
}
<强>更新强>
Project 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
}
...
}
...
答案 1 :(得分:58)
您可以使用以下方法:
@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");
}
}
答案 2 :(得分:21)
根据之前的答案,可以简化它,以匹配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,在Lollipop上它将使用VectorDrawable。
我在@ user3109468
的评论后编辑了这个条件答案 3 :(得分:12)
如果您愿意将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'
}
链接到扩展方法的源here。
请注意,这将适用于Drawable
的任何子类,如果Drawable
是BitmapDrawable
,它将快捷使用基础{{1} }。
答案 4 :(得分:5)
感谢@Alexey
以下是使用[{1}}
扩展程序的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
答案 5 :(得分:1)
使用以下代码转换具有正确纵横比的图像 (例如,用于通知图标):
public static Bitmap getBitmapFromVector(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
Bitmap bitmap;
if (width < height) { //make a square
bitmap = Bitmap.createBitmap(height, height, Bitmap.Config.ARGB_8888);
} else {
bitmap = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0,
drawable.getIntrinsicWidth(), //use dimensions of Drawable
drawable.getIntrinsicHeight()
);
drawable.draw(canvas);
return bitmap;
}
答案 6 :(得分:0)
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));
答案 7 :(得分:0)
如果您的vector
图像intrinsicWidth
和intrinsicHeight
很小,并且您尝试将位图显示为大视图,那么您将看到结果是模糊的。
在这种情况下,您可以为位图提供新的宽度/高度以获得更好的图像(或者可以在xml中增加矢量大小,但可以使用desireWidth
和desireHeight
更加灵活)。
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
}
希望有帮助
答案 8 :(得分:0)
如果您希望能够将输出缩放到所需的输出大小,请尝试以下代码段:
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)
答案 9 :(得分:0)
在API 16上进行了测试-具有矢量可绘制对象的JellyBean
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;
感谢所有人!
答案 10 :(得分:0)
这将为您提供所需大小的位图。另外,它使您可以根据每个图像来保持或不保持透明度,以便在不需要图像的情况下获得更好的性能。
public static Bitmap drawableToBitmap(Resources res, int drawableId,
int width, int height, boolean keepAlpha) {
Drawable drawable = res.getDrawable(drawableId);
Bitmap bmp = createBitmap(width, height, keepAlpha ?
Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
Canvas cvs = new Canvas(bmp);
drawable.setBounds(0, 0, width, height);
drawable.draw(cvs);
return bmp;
}
答案 11 :(得分:0)
对于这里给出的矢量可绘制对象,给定的代码可以帮助我们,但是请记住,如果找不到可绘制对象为NULL,则它可能为空
@Nullable
public static Bitmap drawableToBitmap(Context context, int drawableId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableId);
if (drawable != null) {
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bmp;
}
return null;
}
答案 12 :(得分:0)
创造Vector to Bitmap的独立乐趣
//vectorToBitmapMarker
private fun fromVectorToBitmap(id: Int, color: Int): BitmapDescriptor
{
val vectorDrawable: Drawable? = ResourcesCompat.getDrawable(resources, id, null)
if (vectorDrawable == null)
{
d("VTOB","Resource not found!")
return BitmapDescriptorFactory.defaultMarker()
}
val bitmap = Bitmap.createBitmap(
vectorDrawable.intrinsicWidth,
vectorDrawable.intrinsicHeight,
Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
vectorDrawable.setBounds(0,0,canvas.width, canvas.height)
DrawableCompat.setTint(vectorDrawable, color)
vectorDrawable.draw(canvas)
return BitmapDescriptorFactory.fromBitmap(bitmap)
}
<块引用>
现在对 onMapReady() -> .icon() 进行更改
mMap.addMarker(
MarkerOptions().position(goa)
.title("Marker in Goa")
.draggable(true)
.icon(fromVectorToBitmap(R.drawable.location, Color.parseColor("#FF0560"))))