擦除功能在自定义SurfaceView Android中不起作用
我有一个自定义的surfaceView,它将根据触摸事件绘制曲面。当我在这个视图上绘制一些东西时,它工作得很好。但当我试图抹掉油漆时,什么也没有被抹掉。请在下面找到示例代码段:擦除功能在自定义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
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中定义的日志,但没有此类日志。我错过什么了吗?