18

我有一个适用于 Android 的绘图应用程序,我目前正在尝试为其添加一个真正的橡皮擦。以前,我只是用白色油漆做橡皮擦,但现在我允许使用背景颜色和图像,所以不再这样做了。我通过在透明画布下方放置一个图像视图来做到这一点。

我面临的问题是,每当我启用橡皮擦时,它会在我的手指向下时画出一条纯黑色的轨迹,但一旦我松开它就会变成透明的。请参阅下面的屏幕截图:

这就是我的手指在屏幕上时的样子——一条纯黑色的轨迹 当我的手指还在屏幕上时它的外观

这就是我将手指从屏幕上移开后的样子 我放手后的样子

因此,似乎我已经接近了,但我找不到正确的设置组合来避免在擦除时手指触摸时出现黑色痕迹。以下是一些相关的代码片段:

绘制

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(Color.TRANSPARENT);
    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
    canvas.drawPath(mPath, mPaint);
    canvas.drawPath(mPreviewPath, mPaint);
}

触摸事件

@Override
public boolean onTouchEvent(MotionEvent event) {
    float currentX = event.getX();
    float currentY = event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touchStart(currentX, currentY);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            touchMove(currentX, currentY);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            touchUp(currentX, currentY);
            invalidate();
            break;
    }
    return true;
}

当前尝试橡皮擦设置

public void startEraser() {
    mPaint.setAlpha(0);
    mColor = Color.TRANSPARENT;
    mPaint.setColor(Color.TRANSPARENT);
    mPaint.setStrokeWidth(mBrushSize);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setMaskFilter(null);
    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    mPaint.setAntiAlias(true);
}

还有其他几篇关于橡皮擦的帖子,但大多数都只是说使用PorterDuff.Mode.CLEARsetMakFilter(null)而且应该可以。在我的情况下,它没有。无论我尝试什么,我都会先得到黑色轨迹,然后只有在发布后才能得到想要的结果。

如有必要,我可以提供更多代码。

4

5 回答 5

15

我可以建议您阅读FingerPaint.java
的官方示例 它完全符合您在此处尝试实现的目标。

要在擦除内容时不显示轨迹,请查看onDraw()方法和eraserMode变量:

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(0xFFAAAAAA);
    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
    if (!eraserMode) {
        canvas.drawPath(mPath, mPaint);
    }
}

boolean eraserMode = false;

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    eraserMode = false;
    mPaint.setXfermode(null);
    mPaint.setAlpha(0xFF);
    switch (item.getItemId()) {
        /*...*/
        case ERASE_MENU_ID:
            // Add this line
            eraserMode = true;
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
            return true;
        /*...*/
    }
    return super.onOptionsItemSelected(item);
}
于 2014-08-11T10:55:29.950 回答
10

人们仍在寻找一种更短的方法来删除黑线,同时擦除。只需setLayerType(View.LAYER_TYPE_SOFTWARE, drawPaint);将此行添加到构造函数中即可。干杯!

于 2015-03-11T12:04:39.920 回答
5

以上答案都不适合我。经过一番尝试和一些逻辑,解决了它,检查 ACTION_MOVE

@Override
public boolean onTouchEvent(MotionEvent event) {

    float touchX = event.getX();
    float touchY = event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            isEdited = true;
            drawPath.moveTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_MOVE:
            if(isEraser) {
                drawPath.lineTo(touchX, touchY);
                drawCanvas.drawPath(drawPath, drawPaint);
                drawPath.reset();
                drawPath.moveTo(touchX, touchY);
            } else {
                drawPath.lineTo(touchX, touchY);
            }
            break;
        case MotionEvent.ACTION_UP:
            drawCanvas.drawPath(drawPath, drawPaint);
            drawPath.reset();
            break;
        default:
            return false;
    }

    invalidate();
    return true;
}

和这个

public void setEraser(boolean isEraser) {
    this.isEraser = isEraser;
    if (isEraser) {
        drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    } else {
        drawPaint.setXfermode(null);
    }
}
于 2018-01-20T11:43:31.333 回答
1

您能否评论 canvas.drawPath(mPreviewPath, mPaint) 行并查看它是否有效:

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(Color.TRANSPARENT);
    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
    canvas.drawPath(mPath, mPaint);
    //canvas.drawPath(mPreviewPath, mPaint);
}
于 2014-08-11T02:49:52.993 回答
0

当你想让橡皮擦设置绘画颜色与现实生活中不透明的画布颜色相同时。在 android 中,我们将 set paint color 设置为画布的主题颜色,主要是白色或黑色。

mColor = Color.BLACK;
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(mBrushSize);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
于 2014-08-11T10:13:42.110 回答