You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:20:41