我的应用程序使用我缩放的画布,以便我可以以米为单位指定路径点而不是像素。当我缩放画布时,然后使用path.lineTo()
绘制一条线,加上硬件加速,线条模糊并偏移。关闭硬件加速或使用canvas.drawLine()
时不会发生这种情况。
以下是重现问题的代码:
package com.example.canvasproblem;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
class MyView extends View {
Paint pen = new Paint();
public MyView(Context context) {
super(context);
pen.setStyle(Paint.Style.STROKE);
pen.setStrokeWidth(1f); // 1 meters wide
//this.setLayerType(LAYER_TYPE_SOFTWARE, null);
}
protected void onDraw(Canvas canvas) {
float width_meter = 10.0f; // width of canvas in meters
float width_pxl = canvas.getWidth(); // width of canvas in pixels
float height_pxl = canvas.getHeight(); // height of canvas in pixels
canvas.save();
canvas.translate(width_pxl/2, height_pxl/2); // make center of canvas (0,0)
canvas.scale(width_pxl/width_meter, width_pxl/width_meter); // convert to meters
// path
Path path = new Path();
path.moveTo(0, 0);
path.lineTo(0, 4);
canvas.drawPath(path, pen);
// line
canvas.drawLine(0, 0, 0, 4, pen);
canvas.restore();
}
}
}
以下是问题输出的截图(正确的drawLine()显示在lineTo()之上):
硬件是1024x768平板电脑,运行android 4.1.1。处理器是Rockchip RK30。
我的偏好是使用带有硬件加速的Path,用于点和速度之间的圆形连接。如果我做错了什么来创建这个问题,请告诉我。谢谢
温柔,这是我的第一篇文章。
答案 0 :(得分:6)
这是硬件加速渲染器的限制。在变换之前,路径以其原始大小进行栅格化。在您的情况下,Path将转换为1x4纹理。然后在绘制时缩放该纹理。要解决此问题,请使用Path.transform(Matrix)
直接缩放路径。您还可以在构建路径时使用缩放坐标。
答案 1 :(得分:5)
感谢Romain Guy的回答,这里是drawPath()方法的包装器,它为硬件加速打开和关闭产生相同的结果。它只处理x& y在现有矩阵中的缩放是相同的,并且它可能不是最有效的。
void drawPath(Canvas canvas, Path path, final Paint pen) {
canvas.save();
// get the current matrix
Matrix mat = canvas.getMatrix();
// reverse the effects of the current matrix
Matrix inv = new Matrix();
mat.invert(inv);
canvas.concat(inv);
// transform the path
path.transform(mat);
// get the scale for transforming the Paint
float[] pts = {0, 0, 1, 0}; // two points 1 unit away from each other
mat.mapPoints(pts);
float scale = (float) Math.sqrt(Math.pow(pts[0]-pts[2], 2) + Math.pow(pts[1]-pts[3], 2));
// copy the existing Paint
Paint pen2 = new Paint();
pen2.set(pen);
// scale the Paint
pen2.setStrokeMiter(pen.getStrokeMiter()*scale);
pen2.setStrokeWidth(pen.getStrokeWidth()*scale);
// draw the path
canvas.drawPath(path, pen2);
canvas.restore();
}
答案 2 :(得分:1)
我发现的解决此问题的另一种方法是将Path
绘制到由缓存位图支持的另一个Canvas
,然后将该位图绘制到已传递的位图Canvas
。这消除了我的情况下的模糊和偏移。