在Android上的SurfaceView上的DrawPath

时间:2017-06-08 07:58:12

标签: android

我正在开发相机应用程序,我需要在surfaceView上绘制路径 surfaceView用于预览相机。捕获图片后,我需要在其上绘制路径。一切都很好但是当我第一次画路时它没问题但是当画另一条路时它会移除前一条路径。

这是我正在使用的代码。

// Class is extended from surfaceView and implements SurfaceHolder.Callback
@Override
protected void onDraw(Canvas canvas) {
    Log.i(TAG, "onDraw");
    canvas.drawPath(drawPath, drawPaint);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float touchX = event.getX();
    float touchY = event.getY();
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            drawCanvas = surfaceHolder.lockCanvas();
            drawPath.moveTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_MOVE:
            drawPath.lineTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_UP:
            drawCanvas.drawPath(drawPath, drawPaint);
            drawPath.reset();
            surfaceHolder.unlockCanvasAndPost(drawCanvas);
            break;
        default:
            return false;
    }
    invalidate();
    return true;
}
// other code

问题:如果您尝试绘制另一条路径,则可以首次绘制路径它会移除第一条路径

你能否告诉我我做错了什么。

2 个答案:

答案 0 :(得分:1)

LunarWatcher是对的。

我刚才在答案中做了一些修改。您需要路径ArrayList以及每个当前path,因为如果您只是使用foreach方法中的onDraw循环,就像LunarWatcher所说的那样,您将无法看到绘图路径,直到用户完成绘图。

这是我的代码,我测试并正常工作。

private ArrayList<Path> drawPath;
private Path path;

public constructor(){
    drawPath = new ArrayList<Path>();
    path = null;
} 

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
    if(path != null) {
        canvas.drawPath(path, drawPaint);
    }
    for(Path p : drawPath) {
            canvas.drawPath(p, drawPaint);
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float touchX = event.getX();
    float touchY = event.getY();
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            drawCanvas = surfaceHolder.lockCanvas();
            path = new Path();
            path.moveTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_MOVE:
            path.lineTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_UP:
            drawCanvas.drawPath(path, drawPaint);
            drawPath.add(new Path(path));
            path.reset();
            surfaceHolder.unlockCanvasAndPost(drawCanvas);
            break;
        default:
            return false;
    }
    invalidate();
    return true;
}

希望这对你有用。

答案 1 :(得分:0)

当你invalidate画布时,你基本上清除画布并重绘内容。表示先前在画布上的任何内容都将被删除如果创建移动对象并使画布无效,您将看到对象移动并且绘制的旧位置消失。第一个消失的原因是因为在绘制第二个之后你不会重新绘制它。

考虑一下:

if(something)
    canvas.drawRect(0,0,10,10);

如果something变为假,则您不会绘制该对象并且它会消失。它没有被渲染,所以它即使在那里也没有出现。

与路径相同。你这样做:

drawCanvas.drawPath(drawPath, drawPaint);

对于单一路径。用新的路径替换该路径时的含义,旧路径消失。

小改进:

您不需要手动将其绘制到画布 AND 使用invalidate,因为您重绘了两次。真的很低效。

<强>解决方案:

创建一个drawPaths的ArrayList,当删除指针时,添加当前路径。

然后当你在onDraw中渲染时:

for(Path p : paths){
    //render here
}

这样您可以渲染所有路径而不是最新路径。当您仅渲染最新版本时,旧路径将消失,从而导致您遇到的问题。