Creating an Eraser for an Android Drawing App

791 Views Asked by At

I'm working on a drawing application and am pretty close to release but I'm having issues with the eraser part of the app. I have 2 main screens (fragments) one is just a blank white canvas that the user can draw on with some options and so on. The other is a note taking fragment. This note taking fragment looks like notebook paper. So for erasing on the drawing fragment, I can simply use the background of the canvas and the user wont know the difference. On the note fragment though I cannot do this beacuse I need to keep the background in tact. I have looked into PorterDuffer modes and have tried the clear version and tried to draw onto a separate bitmap but nothing has worked. If there was a way to control what gets draw ontop of what then that would be useful. I'm open to any suggestions, I can't seem to get anything to work.

Ive also played with enabling a drawing cache before erasing and that doesn't work. In addition I tried hardware enabling and that made my custom view behave oddly. Below is the relavent code. My on draw methods goes through a lot of paths because I am querying them in order to allow for some other functionallity.

@Override
    protected void onDraw(Canvas canvas) {

        //draw the backgroumd type
        if(mDrawBackground) {
            //draw the background
            //if the bitmap is not null draw it as the background, otherwise we are in a note view
            if(mBackgroundBitmap != null) {
                canvas.drawBitmap(mBackgroundBitmap, 0, 0, backPaint);
            } else {
                drawBackgroundType(mBackgroundType, canvas);
            }
        }

        for (int i = 0; i < paths.size(); i++ ) {
            //Log.i("DRAW", "On draw: " + i);
            //draw each previous path.
            mDrawPaint.setStrokeWidth(strokeSizes.get(i));
            mDrawPaint.setColor(colors.get(i));
            canvas.drawPath(paths.get(i), mDrawPaint);
        }
        //set paint attributes to the current value
        mDrawPaint.setStrokeWidth(strokeSize);
        mDrawPaint.setColor(mDrawColor);
        canvas.drawPath(mPath, mDrawPaint);

    }

and my draw background method

/**
     * Method that actually draws the notebook paper background
     * @param canvas the {@code Canvas} to draw on.
     */
    private void drawNoteBookPaperBackground(Canvas canvas) {

        //create bitmap for the background and a temporary canvas.
        mBackgroundBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBackgroundBitmap);
        //set the color to white.
        mBackgroundBitmap.eraseColor(Color.WHITE);

        //get the height and width of the view minus padding.
        int height = getHeight() - getPaddingTop() - getPaddingBottom();
        int width = getWidth() - getPaddingLeft() - getPaddingRight();

        //figure out how many lines we can draw given a certain line width.
        int lineWidth = 50;
        int numOfLines = Math.round(height / lineWidth);
        Log.i("DRAWVIEW", "" + numOfLines);


        //iterate through the number of lines and draw them.
        for(int i = 0; i < numOfLines * lineWidth; i+=lineWidth) {
            mCanvas.drawLine(0+getPaddingLeft(), i+getPaddingTop(), width, i+getPaddingTop(), mNoteBookPaperLinePaint);
        }

        //now we need to draw the vertical lines on the left side of the view.
        float startPoint = 30;
        //set the color to be red.
        mNoteBookPaperLinePaint.setColor(getResources().getColor(R.color.notebook_paper_vertical_line_color));

        //draw first line
        mCanvas.drawLine(startPoint, 0, startPoint, getHeight(), mNoteBookPaperLinePaint);
        //space the second line next to the first one.
        startPoint+=20;
        //draw the second line
        mCanvas.drawLine(startPoint, 0, startPoint, getHeight(), mNoteBookPaperLinePaint);

        //reset the paint color.
        mNoteBookPaperLinePaint.setColor(getResources().getColor(R.color.notebook_paper_horizontal_line_color));

        canvas.drawBitmap(mBackgroundBitmap, 0, 0, backPaint);
    }
1

There are 1 best solutions below

0
On BEST ANSWER

To all who see this question I thought I would add how I solved the problem. What I'm doing is creating a background bitmap in my custom view and then passing that to my hosting fragment. The fragment then sets that bitmap as its background for the containing view group so that when I use the PorterDuff.CLEAR Xfermode, the drawn paths are cleared but the background in the fragment parent remains untouched.