4

Can i make it draw the path, where I move my finger to delete with a transparent line, or not draw at all?

This is how i instantiate my eraser:

 OnClickListener eraseListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            mPaint.setColor(0x00000000);
            mPaint.setXfermode(clear);
            mPaint.setAlpha(0x00);
            myView.setPaint(mPaint);
            LogService.log("PaintActivity", "------in eraseListener");

        }
    };

This sets the paint from my View that contains the canvas. Here i have the following motion events:

private void touch_start(float x, float y) {
    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
}
private void touch_move(float x, float y) {
    float dx, dy;
        dx = Math.abs(x - mX);
        dy = Math.abs(y - mY);
    if ((dx >= TOUCH_TOLERANCE) || (dy >= TOUCH_TOLERANCE)) {
        undoPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
        mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            mX = x;
            mY = y;
    }
}
private void touch_up() {
    mPath.lineTo(mX, mY);
    mPath.moveTo(mX, mY);
    canvas.drawPath(mPath, paint);
    mPath.reset();
}
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        touch_start(x, y);
        break;
    case MotionEvent.ACTION_MOVE:
        touch_move(x, y);
        invalidate();
        break;
    case MotionEvent.ACTION_UP:
        touch_up();
        invalidate();
        break;
    }
    return true;
}

Now if i want to erase, as i said, when i move my finger, it draw a black line on that path. and when i take my finger off, on touch_up, it erases what is on the back of the black line it drawn. If i comment the invalidate(); line from the touch_move function, then it will not draw that black line, but also, it will only erase on touch_up. Can't i make it erase in real time?

rosu alin
  • 5,674
  • 11
  • 69
  • 150
  • Offtopic: I've seen that you answered a lot of your own questions which may suggest you aren't putting a lot of effort **before** asking the question. Please consider that. Related to your question, can't you simply make a small path between two consecutive move touch points points and draw/clear that small path(similar to what you make between the move and up touch events), resetting the path after each move? – user Feb 21 '13 at 10:25
  • no, because i need the path to be continuous since the moment i touch the screen (touch_down), untill the moment i unpress the screen (touch_up). Because i need to save the whole path, in case i want to call the Undo function. Also the path used is the same for drawing, erasing, and moving pictures/shapes – rosu alin Feb 21 '13 at 10:46
  • You could have an additional path to store the entire movement made by the user(what you currently use right now) and a temporary small path to do what I said above. – user Feb 21 '13 at 10:52
  • it should be in realtime, and with invalidate, it does that, the only problem is that porter duff draw with a black line, even if i set it to be any other color, or if i set the alpha – rosu alin Feb 21 '13 at 12:54
  • @rosualin Have u solve your issue, because i am also facing the same problem look at my question http://stackoverflow.com/questions/16229496/eraser-with-porterduff-mode-clear-always-draws-a-transparent-line – AndroidDev Apr 26 '13 at 06:36
  • @AndroidCoder, no i did not manage to fix this, the client accepted it this way – rosu alin Apr 26 '13 at 07:17
  • See http://stackoverflow.com/a/23492932/2936131 and you can keep your undo – Sean Webb May 06 '14 at 11:07

4 Answers4

11

I resolved it like this:

private void touch_move(float x, float y) {
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);

        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        mPath.reset();
        mPath.moveTo(mX, mY);

        mX = x;
        mY = y;
    }
}

Here I added a line to the path, drew the path, reset the path and used moveTo in the touch_move method.

On touch_up I only use mPath.reset().

private void touch_up() {

    // kill this so we don't double draw
     mPath.reset();

}

This make my eraser transparent — no black line draw on erasing.

andyg0808
  • 1,367
  • 8
  • 18
Jyoti Mohite
  • 126
  • 2
  • 5
8

just turn HWA off.

or you can add this line in constructor

setLayerType(View.LAYER_TYPE_SOFTWARE, mPaint);
sithmal_
  • 153
  • 2
  • 5
4

To erasing without black line modify your code in onDraw():

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
    if (mMode != PAINT_MODE) {
        return;
    }
    canvas.drawPath(mPath, mPaint);
}

and if you want to make finger erasing more naturally, modify code of touch_move()

if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
    mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
    mX = x;
    mY = y;
    if (mMode != PAINT_MODE) {
        mCanvas.drawPath(mPath, mPaint);
    }
vals
  • 53
  • 2
  • 6
0

Just draw one more transparent bitmap with same size before drawing your original bitmap on canvas.

Bitmap b = Bitmap.createBitmap(orgBM.getWidth(), orgBM.getHeight(), Bitmap.Config.ARGB_8888);

Canvas c = new Canvas();
c.setBitmap(b);

c.drawBitmap(orgBM, 0, 0, null);
Vladimir Vagaytsev
  • 2,871
  • 9
  • 33
  • 36
D_SHARMA
  • 1
  • 3