从矢量drawable获取位图

lil*_*tof 107 android bitmap android-drawable android-vectordrawable

在我的应用程序中,我必须为通知设置一个大图标.LargeIcon必须是一个Bitmap,我的drawables是矢量图像(Android中的新功能,请看这个链接)问题是当我尝试解码一个矢量图像的资源时,我得到一个null返回.

以下是代码示例:

if (BitmapFactory.decodeResource(arg0.getResources(), R.drawable.vector_menu_objectifs) == null)
        Log.d("ISNULL", "NULL");
    else
        Log.d("ISNULL", "NOT NULL");
Run Code Online (Sandbox Code Playgroud)

在这个例子中,当我用一个"普通"图像替换R.drawable.vector_menu_objectifs,例如一个png例如,结果不为空(我得到正确的位图)是否有我缺少的东西?

Ale*_*xey 203

检查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;
}
Run Code Online (Sandbox Code Playgroud)

更新:

项目gradle:

dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0-alpha5'
    }
Run Code Online (Sandbox Code Playgroud)

模块gradle:

android {
    compileSdkVersion 23
    buildToolsVersion '23.0.3'
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 23
        vectorDrawables.useSupportLibrary = true
    }
    ...
}
...
Run Code Online (Sandbox Code Playgroud)

  • 我遇到了这个解决方案的问题.对我来说使用:AppCompatResources而不是ContextCompat修复它:Drawable drawable = AppCompatResources.getDrawable(context,drawableId); (5认同)
  • ````AppCompatDrawableManager```被标记为```@RestrictTo(LIBRARY_GROUP)```所以它是内部的,你不应该使用它(它的API可以更改,恕不另行通知).使用```ContextCompat```代替. (4认同)
  • 这对我很有用.在API 15上运行没有问题 (2认同)

sno*_*per 61

您可以使用以下方法:

@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;
}
Run Code Online (Sandbox Code Playgroud)

我有时与之合并:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 希望@liltof回来并将其标记为答案。需要注意的一件事是,这两种方法都需要targetAPi包装器,但是android studio会告诉您。 (2认同)

Ese*_*far 27

根据之前的答案,可以简化它,以匹配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");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你必须添加你的gradle文件:

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}
Run Code Online (Sandbox Code Playgroud)

在pre-Lollipop上它将使用VectorDrawableCompat,在Lollipop上它将使用VectorDrawable.

编辑

我已根据@ user3109468的评论编辑了这个条件


Dav*_*son 25

如果您愿意使用Android KTX for Kotlin,您可以使用扩展方法Drawable#toBitmap()获得与其他答案相同的效果:

val bitmap = AppCompatResources.getDrawable(requireContext(), drawableId).toBitmap() 
Run Code Online (Sandbox Code Playgroud)

要么

val bitmap = AppCompatResources.getDrawable(context, drawableId).toBitmap() 
Run Code Online (Sandbox Code Playgroud)

要添加此扩展方法和其他有用的扩展方法,您需要将以下内容添加到模块级别 build.gradle

repositories {
    google()
}

dependencies {
    implementation 'androidx.core:core-ktx:1.0.0-alpha1'
}
Run Code Online (Sandbox Code Playgroud)

在此处链接到扩展方法的源.

请注意,这将适用于任何子类,Drawable如果DrawableBitmapDrawable,它将使用底层的快捷方式Bitmap.

  • 对我来说,它与“VectorDrawable”完美配合。 (3认同)

Gun*_*han 6

@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
}
Run Code Online (Sandbox Code Playgroud)

用法示例Activity

val bitmap = this.getBitmapFromVectorDrawable(R.drawable.ic_done_white_24dp)
Run Code Online (Sandbox Code Playgroud)