Note that there are some explanatory texts on larger screens.

plurals
  1. POTrying to create an Eraser Paint for canvas
    text
    copied!<p>I am creating a drawing app that utilizes the DrawingSurfaceView class below. In that class i have a Paint Called eraserPaint that the user can toggle on and off.. When on that paint is suppose to eraser what ever is in its path. but instead its just drawing a black line..</p> <p>When i save out the canvas as a transparent png the eraser is correct but on the screen it shows black.. </p> <p><strong>Screenshot from phone of EraserPaint used to write "Erik" on blob</strong> </p> <p><img src="https://i.stack.imgur.com/Z3SlF.png" alt="enter image description here"> </p> <p><strong>Saved out PNG from canvas</strong> <img src="https://i.stack.imgur.com/7A5BG.png" alt="enter image description here"></p> <p><strong>eraserPaint looks like this:</strong> </p> <pre><code>eraserPaint = new Paint(); eraserPaint.setAlpha(0); eraserPaint.setColor(Color.TRANSPARENT); eraserPaint.setStrokeWidth(60); eraserPaint.setStyle(Style.STROKE); eraserPaint.setMaskFilter(null); eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); eraserPaint.setAntiAlias(true); </code></pre> <p><strong>the WHOLE class</strong></p> <pre><code> public KNDrawingSurfaceView(Context c, float width, float height, KNSketchBookActivity parent) { super(c); myWidth = width; myHeight = height; mBitmap = Bitmap.createBitmap((int) myWidth, (int) myHeight, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); _parent = parent; mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f); tile = new Paint(); tileImage = BitmapFactory.decodeResource(getResources(), R.drawable.checkerpattern); shader = new BitmapShader(tileImage, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); tile.setShader(shader); mPath = new Path(); eraserPaint = new Paint(); eraserPaint.setAlpha(0x00); eraserPaint.setColor(Color.TRANSPARENT); eraserPaint.setStrokeWidth(60); eraserPaint.setStyle(Style.STROKE); //eraserPaint.setMaskFilter(null); eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); eraserPaint.setAntiAlias(true); mBitmapPaint = new Paint(Paint.DITHER_FLAG); mCanvas.drawRect(0, 0, myWidth, myHeight, tile); mCanvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); } @Override protected void onDraw(Canvas canvas) { if (!_parent.isDrawerOpen()&amp;&amp;mPaint!=null) { Log.v("onDraw:", "curent paths size:" + paths.size()); //mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); //canvas.drawPath(mPath, mPaint); for (int i=0;i&lt; paths.size();i++) { tempPaint = paints.get(i); eraserPaint.setStrokeWidth(tempPaint.getStrokeWidth()); if(fills.get(i)){ tempPaint.setStyle(Style.FILL_AND_STROKE); eraserPaint.setStyle(Style.FILL_AND_STROKE); }else{ tempPaint.setStyle(Style.STROKE); eraserPaint.setStyle(Style.STROKE); } if(erasers.get(i)){ //tempPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawPath(paths.get(i), eraserPaint); }else{ //tempPaint.setXfermode(null); canvas.drawPath(paths.get(i), tempPaint); } //canvas.drawPath(paths.get(i), tempPaint); } if(_parent.toggleFill.isChecked()){ mPaint.setStyle(Style.FILL_AND_STROKE); eraserPaint.setStyle(Style.FILL_AND_STROKE); }else{ mPaint.setStyle(Style.STROKE); eraserPaint.setStyle(Style.STROKE); } if(_parent.toggleErase.isChecked()){ //mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawPath(mPath, eraserPaint); }else{ //mPaint.setXfermode(null); canvas.drawPath(mPath, mPaint); } //canvas.drawPath(mPath, mPaint); } } public void onClickUndo() { if (paths.size() &gt; 0) { undonePaths.add(paths.remove(paths.size() - 1)); undonePaints.add(paints.remove(paints.size() - 1)); undoneFills.add(fills.remove(fills.size() - 1)); undoneErasers.add(erasers.remove(erasers.size() - 1)); clearCanvasCache(); invalidate(); } else { } _parent.checkButtonStates(); } public void onClickRedo() { if (undonePaths.size() &gt; 0) { paths.add(undonePaths.remove(undonePaths.size() - 1)); paints.add(undonePaints.remove(undonePaints.size() - 1)); fills.add(undoneFills.remove(undoneFills.size() - 1)); erasers.add(undoneErasers.remove(undoneErasers.size() - 1)); clearCanvasCache(); invalidate(); } else { } _parent.checkButtonStates(); } public void onClickClear() { paths.clear(); paints.clear(); fills.clear(); erasers.clear(); undoneFills.clear(); undonePaths.clear(); undonePaints.clear(); undoneErasers.clear(); clearCanvasCache(); invalidate(); _parent.checkButtonStates(); } public void saveDrawing() { FileOutputStream outStream = null; String fileName = "tempTag"; try { outStream = new FileOutputStream("/sdcard/" + fileName + ".png"); mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream); outStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { } } private float mX, mY; private static final float TOUCH_TOLERANCE = 4; private void touch_start(float x, float y) { undonePaths.clear(); undonePaints.clear(); undoneFills.clear(); mPath.reset(); mPath.moveTo(x, y); mX = x; mY = y; } private void touch_move(float x, float y) { float dx = Math.abs(x - mX); float dy = Math.abs(y - mY); if (dx &gt;= TOUCH_TOLERANCE || dy &gt;= TOUCH_TOLERANCE) { mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); mX = x; mY = y; } } private void touch_up() { mPath.lineTo(mX, mY); // commit the path to our offscreen if(_parent.toggleErase.isChecked()){ mCanvas.drawPath(mPath, eraserPaint); erasers.add(true); paints.add(eraserPaint); }else{ mCanvas.drawPath(mPath, mPaint); erasers.add(false); paints.add(mPaint); } // kill this so we don't double draw paths.add(mPath); if(_parent.toggleFill.isChecked()){ fills.add(true); }else{ fills.add(false); } if(_parent.toggleErase.isChecked()){ erasers.add(true); }else{ erasers.add(false); } _parent.checkButtonStates(); mPath = new Path(); } @Override public boolean onTouchEvent(MotionEvent event) { if(mPaint==null &amp;&amp;!_parent._showingAlert){ _parent.showNoPaintAlert(); } if (!_parent.isDrawerOpen()&amp;&amp;mPaint!=null) { float x = event.getX(); float y = event.getY(); if (x &gt; myWidth) { x = myWidth; } if (y &gt; myHeight) { y = myHeight; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: touch_start(x, y); invalidate(); break; case MotionEvent.ACTION_MOVE: touch_move(x, y); invalidate(); break; case MotionEvent.ACTION_UP: touch_up(); invalidate(); break; } return true; } else { return true; } } public void clearCanvasCache() { mBitmap = Bitmap.createBitmap((int) myWidth, (int) myHeight, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); } } </code></pre> <p>I should add that i am adding this Custom View to a relative layout that has that checkered pattern as the background image..</p> <p>PLEASE PLEASE PLEASE help.. i need that preview image to NOT show black after an eraser paint was used.. i need it to show the checkered pattern behind.. I know the eraser is working as those black eraser marks save out as transparent.</p> <p><strong>NEW NOTE</strong></p> <p>I was playing around and discovered something else thats curious. Experimenting, i tried switching from drawing to the <code>canvas</code> as passed to the <code>onDraw</code> method and directly to the canvas i set up in the contructor called <code>mCanvas</code> and noticed it did not draw as far as i could see.. so I added a log to the <code>onDraw</code> like so:</p> <pre><code> protected void onDraw(Canvas canvas) { Log.v("DRAWING SURFACE", "canvas:"+canvas+" mCanvas:"+mCanvas); </code></pre> <p>which spits out</p> <pre><code>06-21 11:10:43.994: V/DRAWING SURFACE(4532): canvas:android.view.Surface$CompatibleCanvas@42a8c030 mCanvas:android.graphics.Canvas@431df180 </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload