在我的应用程序中,我编写了自己的SVG转换器,将原始SVG XML文件转换为一系列图形向量对象(Paint、Path等),然后应用于Canvas。SVG数据首先被转换为一种类似字节码格式的形式,连同路径列表等一起,这意味着初始XML解析只需要进行一次,之后每次重绘SVG图形都可以相对较快地完成。SVG转换在运行时完成的事实使我能够对各种图形元素执行一些程序操作。例如,我可以在Inkscape中绘制一个图形温度计,在运行时代码会操作仪表的刻度并移动指针。这就是为什么我“需要”使用矢量操作绘制静态背景图形和移动图形,而不是编译静态位图。无论如何,这是我正在做的一点背景信息;我将进入实际问题。
假设一个典型的仪表小部件由两个叠加的视图组成。背景视图包含静态图形(仪表的圆形面、数字图例、刻度线),这些图形是使用Paths绘制的。前景视图包含需要经常重新绘制的指针图形。每个小部件可能会使用RelativeLayout来包含这些子视图。
我意识到,每当调用前景指针视图的onDraw()时,后面的背景视图的onDraw也会被调用。因此,为了优化小部件的重绘时间,我尝试利用Canvas的绘图缓存来处理背景视图。我的做法确实有效,并且结果是重绘速度大幅提高,但问题在于我保存并稍后重新绘制到Canvas的缓存位图从未像使用Paths最初绘制的那样锐利。
我在背景视图的onDraw()方法中使用的基本代码是:
为了尽可能提高位图的质量,我已经做了以下几件事情:
此外(可能超出主要问题的范围),是否有其他技术可以避免在前景移动图形时重新绘制背景矢量图形?据我所知,使用位图缓存是目前我所知道的唯一方法。
提前感谢您的任何建议。
假设一个典型的仪表小部件由两个叠加的视图组成。背景视图包含静态图形(仪表的圆形面、数字图例、刻度线),这些图形是使用Paths绘制的。前景视图包含需要经常重新绘制的指针图形。每个小部件可能会使用RelativeLayout来包含这些子视图。
我意识到,每当调用前景指针视图的onDraw()时,后面的背景视图的onDraw也会被调用。因此,为了优化小部件的重绘时间,我尝试利用Canvas的绘图缓存来处理背景视图。我的做法确实有效,并且结果是重绘速度大幅提高,但问题在于我保存并稍后重新绘制到Canvas的缓存位图从未像使用Paths最初绘制的那样锐利。
我在背景视图的onDraw()方法中使用的基本代码是:
Bitmap bm = null;
onDraw(Canvas canvas){
if(bm!=null){
Paint bitmapPaint = new Paint();
bitmapPaint.setAntiAlias(false);
bitmapPaint.setFilterBitmap(false);
bitmapPaint.setDither(false);
canvas.drawBitmap(bm, 0, 0, bitmapPaint);
return;
}
... Vector drawing to the Canvas using Path objects happens here,
performed by the SVG converter object ...
setDrawingCacheEnabled(true);
setDrawingCacheQuality(DRAWING_CACHE_QUALITY_HIGH);
bm = Bitmap.createBitmap(getDrawingCache());
}
为了尽可能提高位图的质量,我已经做了以下几件事情:
确保缓存绘制质量高。
在绘制位图时,使用一个关闭反锯齿、抖动等功能的Paint对象(bitmapPaint)。
知道任何对位图的缩放都会立即影响其质量,我(希望)确保不需要对位图进行缩放。我将视图大小设置为与原始SVG图像完全相同,这意味着我的SVG转换代码不会对画布进行缩放。scale()调用总是由SVG转换器执行,但在当前情况下,它的参数是canvas.scale(1,1)。如果我故意更改视图的宽度/高度与原始SVG图像不匹配,则Canvas缩放不再是1,1,那么位图的质量损失就非常明显。
此外(可能超出主要问题的范围),是否有其他技术可以避免在前景移动图形时重新绘制背景矢量图形?据我所知,使用位图缓存是目前我所知道的唯一方法。
提前感谢您的任何建议。