我想在我的应用中展示一个可缩放且可滚动的类似地图的SVG。在不编写自己的库等的情况下执行此操作的唯一方法是使用现有库,所有这些库似乎都将SVG呈现为Bitmap
,例如,可以将其分配给ImageView
。
底层位图很快变得非常大,可能导致内存不足异常。如何仅将可能较大和/或缩放的SVG的一部分绘制为Bitmap
?扩展小位图看起来很糟糕,不是一种选择。
我将自己回答这个问题,因为我一直在寻找答案,发现它遍布整个网络(但不是在这里),并认为它可能对其他人有帮助。
答案 0 :(得分:1)
你能否使用谷歌的svg-android图书馆?在呈现之前,您可以scale将Canvas
设置为正确的大小。
答案 1 :(得分:0)
这会像Google地图的工作原理吗?在放大和缩小时,它们似乎会平铺并增加/减少细节。
我过去做过类似的事情,不确定谷歌是怎么做的,但我的计划对我来说非常好。我所做的是将我的地图划分为矩形区域,然后我将计算哪些区域具有可见的任何部分并仅从这些区域提取数据。如果用户放大,每个矩形区域被细分以提供更多细节。我一直细分到我想要的水平,我停在三,因为我使用10 X 10网格,所以每个级别实际上是10的放大倍数 - 在第三级,我正在观看我在第一级观看的细节的100倍,这足以满足我的需要。
我甚至能够为此设置动画,这样当你放大时,你似乎能够“平稳地”“飞近”地形。
答案 2 :(得分:0)
首先,我使用libsvg-android,它需要NDK,但似乎非常快,特别是如果你不得不经常重绘你的SVG。实际上,我正在使用库的this modified version,它使您能够查询SVG文档中指定的SVG的宽度和高度。
我的第一个方法是:
long svgID = SvgRaster.svgAndroidCreate();
SvgRaster.svgAndroidParseBuffer(svgID, svgString);
SvgRaster.svgAndroidSetAntialiasing(svgID, true);
Bitmap bitmap = Bitmap.createBitmap(500, 500, Bitmap.Config.RGB_565);
SvgRaster.svgAndroidRenderToAreaUniform(svgID, new Canvas(bitmap), -300, -200, 1500, 1500);
首先,解析SVG源。然后,创建Bitmap
,稍后将分配给ImageView
。接下来,SVG被渲染(缩放到1500x1500像素大小)到位图。请注意应用的转换(-300,-200),因为用户已滚动图像视图。
这不起作用。似乎不支持负偏移。
相反,画布必须像这样翻译:
Canvas canvas = new Canvas(bitmap);
canvas.translate(-300, -200);
SvgRaster.svgAndroidRenderToAreaUniform(svgID, canvas, 0, 0, 1500, 1500);
这可以按预期工作。 SVG的翻译应用于画布;通过调整渲染SVG的大小来应用比例。通过这种方式,您可以拥有一个大型SVG文档,并将您感兴趣的比例渲染为更小的位图。
我编写了一个ImageView
子类,它可以在x和y方向上滚动并可缩放。其图像资源是SVG的低分辨率光栅图像。当用户滚动或缩放图像时,将显示此版本的SVG。当用户停止与图像交互时,我将SVG的当前可见部分渲染为图像视图大小的Bitmap
,并绘制此图像而不是低分辨率图像。