我有以下代码来激活/停用橡皮擦:
public PorterDuffXfermode clear = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
eraseB.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!eraser) {
eraser = true;
eraseB.setImageResource(R.drawable.erase_on);
paint = new Paint(Paint.DITHER_FLAG);
paint.setColor(0x00000000);
paint.setAlpha(0x00);
paint.setXfermode(clear);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(stroke);
paintv.setPaint(paint);
} else {
eraser = false;
eraseB.setImageResource(R.drawable.erase);
paint = new Paint(Paint.DITHER_FLAG);
paint.setDither(true);
paint.setXfermode(null);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(stroke);
paintv.setPaint(paint);
}
}
});
setPaint来自我的自定义视图:
public void setPaint(Paint paint) {
this.paint = paint;
LogService.log("in setPaint", "paint = " + paint);
}
和 onDraw 我使用:
canvas.drawPath(mPath, paint);
如果我停用橡皮擦,它会画一条红线,但相反,如果我激活橡皮擦,它会画一条黑线而不是擦除。我该如何解决这个问题
Canvas 不支持橡皮擦,而 Bitmap 支持。
基本解决方法:
-
创建另一个画布
-
创建位图
-
将该位图设置为该画布
public void init(int width, int height) { Log.i(TAG,"init with "+width+"x"+height); foreground = Bitmap.createBitmap(width, height, Config.ARGB_8888); cacheCanvas = new Canvas(); cacheCanvas.setBitmap(foreground); }
-
记录该位图上的触摸,包括油漆和橡皮擦
public boolean onTouchEvent(MotionEvent event) { float eventX = event.getX(); float eventY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: currentStroke = new Stroke(); currentStroke.color = paint; currentStroke.path.moveTo(eventX, eventY); currentStroke.path.lineTo(eventX, eventY); synchronized (strokes) { strokes.add(currentStroke); } lastTouchX = eventX; lastTouchY = eventY; // There is no end point yet, so don't waste cycles invalidating. return true; case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: // Start tracking the dirty region. resetDirtyRect(eventX, eventY); // When the hardware tracks events faster than they are delivered, // the // event will contain a history of those skipped points. int historySize = event.getHistorySize(); for (int i = 0; i < historySize; i++) { float historicalX = event.getHistoricalX(i); float historicalY = event.getHistoricalY(i); expandDirtyRect(historicalX, historicalY); if (i == 0) { lastX = historicalX; lastY = historicalY; currentStroke.path.lineTo(historicalX, historicalY); } else { currentStroke.path.quadTo(lastX, lastY, (historicalX + lastX) / 2, (historicalY + lastY) / 2); } } // After replaying history, connect the line to the touch point. if(historySize==0){ long duration=event.getEventTime()-event.getDownTime(); float offset=0.1f; if(duration<300){ offset=50.0f/duration; } currentStroke.path.lineTo(eventX+offset, eventY+offset); }else{ currentStroke.path.lineTo(eventX, eventY); } synchronized (strokes) { strokes.add(currentStroke); } break; default: return false; } // Include half the stroke width to avoid clipping. float width = paint.getStrokeWidth() / 2; invalidate((int) (dirtyRect.left - width), (int) (dirtyRect.top - width), (int) (dirtyRect.right + width), (int) (dirtyRect.bottom + width)); lastTouchX = eventX; lastTouchY = eventY; return true; }
-
在视图的画布上绘制该位图
protected void onDraw(Canvas canvas) { synchronized (strokes) { if (strokes.size() > 0) { for (Stroke s : strokes) { cacheCanvas.drawPath(s.path, s.color); } canvas.drawBitmap(foreground, 0, 0, null); strokes.clear(); } } }
如果您在纯色背景上绘画,请在画笔中使用与背景相同颜色的油漆,画笔的行为就像橡皮擦一样。