【问题标题】:VectorDrawable: How to position it on canvas?VectorDrawable:如何在画布上定位它?
【发布时间】:2016-06-03 16:35:45
【问题描述】:

对于我的自定义视图:

MyCustomView extends View 

我做了一个 VectorDrawable

mMyVectorDrawable = VectorDrawableCompat.create(getContext().getResources(), R.drawable.ic_some_image, null);

我已经设定了界限

mMyVectorDrawable.setBounds(0, 0, mMyVectorDrawable.getIntrinsicWidth(), mMyVectorDrawable.getIntrinsicHeight());

然后我把它画在画布上

mMyVectorDrawable.draw(canvas);

我在位置 0,0 看到图像

但是我该如何定位呢?如何定位 Rect,我认为setBounds 的前两个参数是开始绘制位置的 X 和 Y 坐标,但这只会影响大小。

如何将我的矢量可绘制对象放置在画布上?

【问题讨论】:

  • 在绘图前translate() 你的CanvassetBounds(x,y, intrinsic_width + x, intrinsic_height + y),虽然我不确定第二种方式...

标签: android android-canvas android-vectordrawable


【解决方案1】:

您可以在绘制可绘制对象之前翻译您的画布。

mMyVectorDrawable.setBounds(0, 0, width, height);
canvas.translate(dx, dy);
mMyVectorDrawable.draw(canvas);

dxdy 指定了从坐标(0, 0) 开始绘制下一个可绘制对象的偏移量。

如果你愿意,你也可以在之后撤消翻译:

canvas.translate(-dx, -dy);

【讨论】:

  • 您可以在对画布进行操作之前使用canvas.save(),在操作之后使用canvas.restore()来不做“反向”翻译
【解决方案2】:

这个问题有点老了,但如果它可以帮助某人,我有一个基于this one的答案。

这个想法是使用以下方法获取可绘制的矢量:

Drawable drawable = AppCompatDrawableManager.get().getDrawable(context, R.drawable.my_drawable);

然后我们直接从这个 Drawable 中获取我们想要保持质量的大小的 Bitmap。然后,因为我们有一个位图,我们可以把它画到我们想要的地方。

注意:在您的 build.gradle 的 defaultConfig 部分中,不要忘记将这一行用于复古兼容性:

vectorDrawables.useSupportLibrary = true

下面是从 Drawable 中获取 Bitmap 的代码:

/**
 * Extract the Bitmap from a Drawable and resize it to the expectedSize conserving the ratio.
 *
 * @param drawable   Drawable used to extract the Bitmap. Can be null.
 * @param expectSize Expected size for the Bitmap. Use {@link #DEFAULT_DRAWABLE_SIZE} to
 *                   keep the original {@link Drawable} size.
 * @return The Bitmap associated to the Drawable or null if the drawable was null.
 * @see <html><a href="https://stackoverflow.com/a/10600736/1827254">Stackoverflow answer</a></html>
 */
public static Bitmap getBitmapFromDrawable(@Nullable Drawable drawable, int expectSize) {
    Bitmap bitmap;

    if (drawable == null) {
        return null;
    }

    if (drawable instanceof BitmapDrawable) {
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        if (bitmapDrawable.getBitmap() != null) {
            return bitmapDrawable.getBitmap();
        }
    }

    if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
        bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
    } else {
        float ratio = (expectSize != DEFAULT_DRAWABLE_SIZE)
                ? calculateRatio(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), expectSize)
                : 1f;

        int width = (int) (drawable.getIntrinsicWidth() * ratio);
        int height = (int) (drawable.getIntrinsicHeight() * ratio);

        bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    }

    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);

    return bitmap;
}

/**
 * Calculate the ratio to multiply the Bitmap size with, for it to be the maximum size of
 * "expected".
 *
 * @param height   Original Bitmap height
 * @param width    Original Bitmap width
 * @param expected Expected maximum size.
 * @return If height and with equals 0, 1 is return. Otherwise the ratio is returned.
 * The ration is base on the greatest side so the image will always be the maximum size.
 */
public static float calculateRatio(int height, int width, int expected) {
    if (height == 0 && width == 0) {
        return 1f;
    }
    return (height > width)
            ? expected / (float) width
            : expected / (float) height;
}

【讨论】:

  • 截至(至少)支持 lib 26.0.2(可能更早?)当您尝试使用 AppCompatDrawableManager 时,它会抱怨您在这里尝试使用非公共 API .我认为正确的选择是使用ContextCompat.getDrawable(context, id)
  • 我在写这个答案时使用的是支持库的25.3.1 版本。但你是对的,我尝试使用更新的版本('26.0.2'),看来你不能再使用这个类了。 the documentation 中甚至没有提到它。它适用于您的解决方案吗? (ContextCompat.getDrawable(context, id))
  • 是的。这是我在栅格化矢量资产时使用的。
【解决方案3】:

正如@pskink 所说,这很好用:

setBounds(x, y, intrinsic_width + x, intrinsic_height + y)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多