如何在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
相关产品推荐
相关产品推荐

