将Canvas缩放以调整Android中的SVG大小

10

我对这个问题感到很困惑,希望有人能帮助我。

我使用svg-android从SVG获取可绘制对象,但是这个可绘制对象没有按比例缩放到视图大小。我找到的所有资料都说应该直接在画布上绘制并重新调整画布大小,但是当我尝试时,似乎只改变了边界而未缩放图像。

目前我尝试过以下方法:

ImageView testview = (ImageView)findViewById(R.id.testview);

//Get SVG and convert to drawable
SVG vector = SVGParser.getSVGFromResource(getResources(),R.drawable.testvector);
Drawable test = vector.createPictureDrawable();

testview.setBackground(test);  //displays fine, but won't scale to the dimensions of
                               //the View

//function that clips the image but doesn't scale:
Drawable testTwo = new CustomPictureDrawable(vector.getPicture(), 
(float)0.5, (float)0.5);

testView.setBackground(testTwo);

class CustomPictureDrawable extends PictureDrawable {
   private float scalex, scaley;

public CustomPictureDrawable(Picture picture, float scalex, float scaley) {
    super(picture);
    this.scalex = scalex;
    this.scaley = scaley;
}

@Override
public void draw(Canvas canvas) {
    Matrix original = canvas.getMatrix();
    canvas.scale(scalex, scaley);
    super.draw(canvas);
    canvas.setMatrix(original);
}
}

//doesn't display anything
Picture testThree = vector.getPicture();

Bitmap b = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_4444);
Canvas c = new Canvas(b);

c.drawPicture(testThree, new Rect(0,0,10,10));

testview.draw(c);

我还发现了一个可以创建缩放位图的函数,但图片质量会明显降低,所以我可能最好还是使用缩放的PNG图片。显然,我缺少某些知识,我的经验不足,这让我感到非常沮丧。
我希望能够让svg-android在提取Picture或PictureDrawable之前完全重新调整SVG的大小,但我无法弄清楚如何通过SVGParser进行步骤,并且在每个坐标对上运行乘数可能会极大地消耗资源。
[编辑] 缩放和重绘图片并将其分配给视图的唯一方法是创建自定义视图并覆盖OnDraw吗?
Picture testThree = vector.getPicture();

Bitmap b = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_4444);
Canvas c = new Canvas(b);

c.drawPicture(testThree, new Rect(0,0,10,10));

//CustomView extends ImageView or Button or whatever with OnDraw overridden and no
//other changes 
CustomView testview = (CustomView)findViewById(R.id.testview); 

testview.OnDraw(c);

我是否正确理解?Canvas c 会覆盖默认画布(这正是我想要的),对吗?

2个回答

8

我想出了解决方法。或者至少找到了一种可行的方法。答案在那个我不喜欢的缩放位图函数中直接呼之欲出。我对Picture类和Draw调用的工作方式存在根本误解。

看起来解决问题的代码:

//Get a Picture from the SVG
SVG vector = SVGParser.getSVGfromResource(getResources(), R.raw.testvector);

Picture test = vector.getPicture();

//Redraw the picture to a new size
Bitmap bitmap = Bitmap.createBitmap(desired width, desired height, config);

Canvas canvas = new Canvas(bitmap);

Picture resizePicture = new Picture();

canvas = resizePicture.beginRecording(desiredWidth, desiredGeight);

canvas.drawPicture(test, new Rect(0,0,desiredWidth, desiredHeight);

resizePicture.endRecording();

//get a drawable from resizePicture
Drawable vectorDrawing = new PictureDrawable(resizePicture);

我可以通过从getWidth()和getHeight()调用中获取desiredWidth和desiredHeight,并在最后使用setBackground(vectorDrawing)将其放置在View上,使其适应任何我想要的视图大小。

2
假设您的解决方案在自定义视图的onDraw方法中,并且假设您已经找出了不直接调用该方法的方法...;-) 您不必对创建新的画布或甚至位图做任何处理。这样做会导致使用svg时失去效率收益(与内存相关)。相反,您可以只调用canvas.drawPicture(vector.getPicture(), new Rect(0,0, width, height)),并使用传入onDraw方法的画布。如果您想使您的视图类更易于扩展,还可以添加一个styleable属性,指示原始svg的名称,然后... - wkhatch
(2) 然后使用String resourceName = a.getString(R.styleable.YouViewClassName_yourViewsCustomAttributeName);访问与原始名称相对应的资源id。svgResourceId = getResources().getIdentifier(resourceName, "raw", getContext().getPackageName()); - wkhatch
哦,还有a变量是一个TypedArray对象,它使您可以访问为视图指定的所有可样式化属性,并且通常会在构造函数中设置,或者更好地说,在构造函数调用的简单方法中设置。在任一构造函数的主体中,您可以执行以下操作:final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.YourCustomViewClassName, defStyle, 0); - wkhatch

6
我遇到了类似的问题,以下是我学到的内容以及我是如何解决的。 首先,我尝试直接将我的svg渲染到画布中。
svg.renderToCanvas(canv);

我想要的尺寸在图片库中没有。然后我尝试使用

调整图片大小。
svg.renderToCanvas(canv,new RectF(0,0,200,200));

并且

svg.setDocumentWidth(200);
svg.renderToCanvas(canv);

但两者都不起作用,所以我开始查看我的SVG。问题是我的SVG是这样开始的

<svg width="66.3679625" height="100.4148375" xmlns="http://www.w3.org/2000/svg">

一旦在 SVG 中设置了宽度和高度,似乎无法在代码中后续更改。在 AndroidSvgFAQ 中也有一个答案,他们建议删除这些属性。因此,我将其更改为

 <svg version="1.1" viewBox="0 0 1280 696" xmlns="http://www.w3.org/2000/svg">

视图框(viewBox)属性是SVG图片的框架,因此如果我现在使用上面的代码。
svg.setDocumentWidth(200);
svg.renderToCanvas(canv);

我获取了左上角坐标为(0,0),右下角坐标为(1200,696)的框的内容,并将其调整大小,使宽度为200。您可以更改比率的行为,最初保持比率不变。请注意,SVG中可以省略宽度、高度和ViewBox,并通过编程方式设置ViewBox。
svg.setDocumentViewBox(0,0,width,height);

要了解更多关于ViewBox属性的内容,请查看W3ViewBox

像黄油一样顺畅! - whitepearl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接