擦除功能在自定义SurfaceView Android中不起作用

擦除功能在自定义SurfaceView Android中不起作用,android,android-canvas,surfaceview,erase,Android,Android Canvas,Surfaceview,Erase,我有一个自定义的surfaceView,它将根据触摸事件绘制曲面。当我在这个视图上绘制一些东西时,它工作得很好。但当我试图抹掉油漆时,什么也没有被抹掉。请在下面找到示例代码段: public class MySurfaceView extends SurfaceView { private static final String TAG = "FreeHandDrawing"; public static Canvas mCanvas; SurfaceHolder holder; private

我有一个自定义的surfaceView,它将根据触摸事件绘制曲面。当我在这个视图上绘制一些东西时,它工作得很好。但当我试图抹掉油漆时,什么也没有被抹掉。请在下面找到示例代码段:

public class MySurfaceView extends SurfaceView {
private static final String TAG = "FreeHandDrawing";
public static Canvas mCanvas;
SurfaceHolder holder;
private static Path path;
private Paint paint;
private ArrayList<Path> pathArrayList = new ArrayList<>();
private boolean freeHandMode;

public MySurfaceView(Context context, AttributeSet attrs) {
    super(context, attrs);
    freeHandMode = false;
    path = new Path();
    holder = getHolder();
    holder.setFormat(PixelFormat.TRANSPARENT);
    setDrawingCacheEnabled(true);

    this.setZOrderOnTop(true);

    paint = new Paint();
    paint.setAntiAlias(true);
    paint.setColor(0xFF22FF11);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeCap(Paint.Cap.ROUND);
    paint.setStrokeWidth(8);

}


@Override
public boolean onTouchEvent(MotionEvent event) {

    if(freeHandMode) {

        if (event.getAction() == MotionEvent.ACTION_DOWN) {

            Log.d("Action", "Placed");
            path.moveTo(event.getX(), event.getY());

        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {

            Log.d("Action", "Moved");
            path.lineTo(event.getX(), event.getY());
            pathArrayList.add(path);

        }

        mCanvas = holder.lockCanvas();
        if (mCanvas != null) {
            if (pathArrayList.size() > 0) {

                mCanvas.drawPath(pathArrayList.get(pathArrayList.size() - 1), paint);

            }
            holder.unlockCanvasAndPost(mCanvas);

        } else {
            Log.d(TAG, "Canvas is NULL");
        }
    }
    invalidate();
    return true;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Log.d(TAG, "On draw called");

}

public void eraseDrawing() {
    pathArrayList.clear();
    invalidate();
}

public void drawEnableDisable(boolean mode) {
    freeHandMode = mode;
  }
}                                                  
公共类MySurfaceView扩展了SurfaceView{
私有静态最终字符串标记=“FreeHandDrawing”;
公共静态画布mCanvas;
表面焊钳;
私有静态路径;
私人油漆;
私有ArrayList路径ArrayList=新ArrayList();
私有布尔自由模式;
公共MySurfaceView(上下文、属性集属性){
超级(上下文,attrs);
freeHandMode=false;
路径=新路径();
holder=getHolder();
holder.setFormat(PixelFormat.TRANSPARENT);
setDrawingCacheEnabled(真);
这个.setZOrderOnTop(true);
油漆=新油漆();
paint.setAntiAlias(真);
paint.setColor(0xFF22FF11);
绘制.设置样式(绘制.样式.笔划);
绘制.设置行程连接(绘制.连接.圆形);
油漆固定行程盖(油漆固定行程盖圆形);
油漆。设置行程宽度(8);
}
@凌驾
公共布尔onTouchEvent(运动事件){
if(自由手模式){
if(event.getAction()==MotionEvent.ACTION\u向下){
日志d(“行动”、“放置”);
moveTo(event.getX(),event.getY());
}else if(event.getAction()==MotionEvent.ACTION\u MOVE){
日志d(“行动”、“移动”);
lineTo(event.getX(),event.getY());
添加(路径);
}
mCanvas=holder.lockCanvas();
如果(mCanvas!=null){
如果(pathArrayList.size()>0){
drawPath(pathArrayList.get(pathArrayList.size()-1),paint);
}
支架。解锁CanvasandPost(mCanvas);
}否则{
Log.d(标记“Canvas为NULL”);
}
}
使无效();
返回true;
}
@凌驾
受保护的void onDraw(画布){
super.onDraw(帆布);
Log.d(标记为“抽签通知”);
}
公共图纸(){
pathArrayList.clear();
使无效();
}
公共无效抽屉可禁用(布尔模式){
自由模式=模式;
}
}                                                  

上面的代码有什么问题?

您应该将图形代码保存在
onDraw
方法中

@Override
protected void onDraw(Canvas canvas) {
    // In case you want to delete/erase when path array/list is cleared.
    if (pathArrayList.size() == 0) {
        canvas.drawColor(0, Mode.CLEAR);
    }
    // In case, you want to draw all paths also in onDraw
    for(Path path : pathArrayList) {
        canvas.drawPath(path, paint);
    }
}
清除路径数组(列表)后,调用invalidate()时,将触发onDraw

注意:您应该在onTouchEvent()的末尾调用invalidate()来告诉系统更新屏幕。调用invalidate()将使框架最终调用onDraw()

此外,不应使用
lockCanvas
获得的
canvas
,因为它不会被硬件加速。相反,您应该使用作为onDraw()本身参数传递的画布


您可以选择通过不必绘制每帧路径的拉列表,而是使用特殊标志处理擦除/重画等操作,使系统变得更智能。否则,只需渲染最近调用onTouchEvent()生成的最新路径。

感谢Bajaj的回复。如果我尝试在onTocuhEvent中绘制,会影响性能吗?。此外,您上面给出的代码似乎对绘制或擦除没有任何影响,它不起作用。您确定要在视图上调用invalidate()吗?如果视图已无效,则在渲染过程中框架将调用yes onDraw()。它可能位于不同的线程(渲染线程)中,因此不建议在onTouchEvent(从UI/主线程调用)中执行复杂操作。onDraw方法未触发,我已检查onDraw中定义的日志,但没有此类日志。我错过什么了吗?