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

如何在ImageView的用户触摸位置绘制圆并避免重复绘制主图

解决ImageView触摸画圆避免重复绘制主图的方案

嘿,这个问题我之前帮不少开发者捋清楚过——你现在的方案每次都从原始Bitmap重绘,自然会重复画主图,效率不高。其实核心思路是把主图和触摸绘制的内容分层存储,让主图只画一次,触摸的圆都画在一个持久化的叠加层上,具体实现步骤如下:

核心思路

我们需要维护两个Bitmap:

  • 一个是原始主图Bitmap:只在初始化时加载,后续不再修改
  • 一个是叠加层Bitmap:和主图尺寸完全一致,专门用来存储所有用户触摸绘制的圆,这个Bitmap对应的Canvas可以长期保留,每次触摸直接在上面画圆就行

这样每次重绘时,只需要先画原始主图,再叠加这个保存了所有圆的Bitmap,就不用重复绘制主图了。

具体代码实现

我们可以自定义一个继承自ImageView的类,来封装这个逻辑:

public class TouchDrawImageView extends ImageView {
    private Bitmap mOriginalBitmap; // 原始主图
    private Bitmap mOverlayBitmap;  // 叠加层Bitmap,存储所有绘制的圆
    private Canvas mOverlayCanvas;  // 叠加层对应的Canvas,长期保留
    private Paint mCirclePaint;     // 画圆的画笔

    public TouchDrawImageView(Context context) {
        super(context);
        init();
    }

    public TouchDrawImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        // 初始化画圆的画笔
        mCirclePaint = new Paint();
        mCirclePaint.setColor(Color.RED);
        mCirclePaint.setStyle(Paint.Style.STROKE);
        mCirclePaint.setStrokeWidth(5f);
        mCirclePaint.setAntiAlias(true);
    }

    // 设置原始主图的方法
    public void setOriginalBitmap(Bitmap bitmap) {
        mOriginalBitmap = bitmap;
        // 创建和主图同尺寸的叠加层Bitmap
        mOverlayBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        mOverlayCanvas = new Canvas(mOverlayBitmap); // 保存这个Canvas,后续直接用
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mOriginalBitmap != null) {
            // 1. 先画原始主图——只需要画一次(后续重绘时,主图内容不变)
            canvas.drawBitmap(mOriginalBitmap, 0, 0, null);
            // 2. 再画叠加层——里面保存了所有之前画的圆
            canvas.drawBitmap(mOverlayBitmap, 0, 0, null);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mOriginalBitmap == null || mOverlayCanvas == null) {
            return super.onTouchEvent(event);
        }

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // 获取触摸坐标
            float x = event.getX();
            float y = event.getY();
            // 直接在叠加层的Canvas上画圆——这个Canvas的内容会保留
            mOverlayCanvas.drawCircle(x, y, 20, mCirclePaint);
            // 触发重绘,此时onDraw只需要合并主图和叠加层
            invalidate();
            return true;
        }
        return super.onTouchEvent(event);
    }
}

关键细节说明

  • 叠加层的持久化:mOverlayCanvas是在初始化叠加层Bitmap时创建的,之后每次触摸都直接用这个Canvas画圆,所有绘制的内容都会保存在mOverlayBitmap里,不会丢失
  • 重绘逻辑优化:onDraw方法里先画原始主图,再画叠加层,主图只需要加载一次,后续重绘不需要重新绘制主图,只需要把叠加层盖上去就行
  • 性能提升:相比每次从原始Bitmap重新绘制,这种分层的方式减少了大量重复绘制操作,尤其是主图尺寸较大时,性能提升会很明显

额外注意事项

  • 如果需要支持清除所有绘制的圆,只需要重新创建mOverlayBitmap和mOverlayCanvas,然后调用invalidate()即可
  • 要注意内存占用:叠加层Bitmap和主图尺寸一致,所以如果主图很大,要考虑内存是否足够,可以根据实际情况做压缩处理

内容的提问来源于stack exchange,提问作者stckskmr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:02:58