title: Trying to create an Eraser Paint for canvas
body: <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>