Android Studio中如何通过按钮清除自定义DrawView的绘制内容?
解决自定义笔迹View的清除功能问题
你的核心问题在于错误地使用了静态Canvas对象——Canvas是系统在onDraw()时临时传入的,静态引用它会引发不可预知的问题,而且这根本不是清除笔迹的正确思路。
正确的做法是:在自定义的DrawView中封装清除逻辑,因为笔迹是存在Path对象里的,只要重置Path并触发重绘即可,不需要直接操作Canvas。
第一步:修改DrawView类
添加一个公开的清除方法,重置绘制路径并通知View重绘:
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; public class DrawView extends View { private Paint drawPaint; private Path path = new Path(); // 删掉静态Canvas,完全不需要 // static Canvas canvas; public DrawView(Context context, AttributeSet attrs) { super(context, attrs); setFocusable(true); setFocusableInTouchMode(true); setupPaint(); } private void setupPaint() { drawPaint = new Paint(); drawPaint.setColor(Color.BLACK); drawPaint.setAntiAlias(true); drawPaint.setStrokeWidth(5); drawPaint.setStyle(Paint.Style.STROKE); drawPaint.setStrokeJoin(Paint.Join.ROUND); drawPaint.setStrokeCap(Paint.Cap.ROUND); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 不要再把Canvas赋值给静态变量 canvas.drawPath(path, drawPaint); } // 添加清除方法 public void clearCanvas() { path.reset(); // 重置绘制路径 invalidate(); // 通知View重绘,此时onDraw会绘制空路径,相当于清除笔迹 } @Override public boolean onTouchEvent(MotionEvent event) { float pointX = event.getX(); float pointY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: path.moveTo(pointX, pointY); break; case MotionEvent.ACTION_MOVE: path.lineTo(pointX, pointY); break; default: return false; } postInvalidate(); return true; } }
第二步:修改Fragment中的点击事件
把drawView的类型从View改成DrawView(或强制转换),调用刚添加的clearCanvas()方法:
import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import com.app.ssl.R; public class DrawviewFragment extends Fragment { private View root; // 直接用DrawView类型,避免类型转换 private DrawView drawView; private Button btnClear; private Button btnSave; public View onCreateView( @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { root = inflater.inflate(R.layout.fragment_drawview, container, false); drawView = root.findViewById(R.id.DrawingView); btnClear = root.findViewById(R.id.btnClean1); btnSave = root.findViewById(R.id.btnSave); btnClear.setOnClickListener(v -> { // 调用DrawView的清除方法 drawView.clearCanvas(); }); btnSave.setOnClickListener(v -> { System.out.println("SAVE"); }); return root; } }
为什么这个方法有效?
你的笔迹实际上存储在Path对象中,每次onDraw()都会把这个Path绘制到Canvas上。调用path.reset()清空路径后,再用invalidate()触发重绘,onDraw()就会绘制空路径,视觉上就实现了画布清除的效果。
这种方式符合Android View的绘制生命周期,避免了直接操作Canvas带来的风险。
内容的提问来源于stack exchange,提问作者Wabi-Sabi
相关产品推荐
相关产品推荐

