how to expand drawing area of canvas

-1

How can I extend the drawing area when it reached the end and there is an issue in clear function when the user clears the screen using clearCanvas() and gets pressed undo() button then the paint color and stroke-width behavior changed. how can I fix it? And now I want to support pdf file in drawing area also for draw over it.

Below is my custom view code and screenshot:

package co.ctdworld.sketchapp;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;

public class DrawingView extends View
{
    private Path mDrawPath;
    private Paint mBackgroundPaint;
    private Paint mDrawPaint;
    private Canvas mDrawCanvas;
    private Bitmap mCanvasBitmap;

    private ArrayList<Path> mPaths = new ArrayList<>();
    private ArrayList<Paint> mPaints = new ArrayList<>();
    private ArrayList<Path> mUndonePaths = new ArrayList<>();
    private ArrayList<Paint> mUndonePaints = new ArrayList<>();
    private ArrayList<Path> mLastPaths = new ArrayList<>();
    private ArrayList<Paint> mLastPaints = new ArrayList<>();

    // Set default values
    private int mBackgroundColor = 0xFFFFFFFF;
    private int mPaintColor = getContext().getResources().getColor(R.color.colorPrimaryDark);
    private int mStrokeWidth = 8;

    public DrawingView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init();
    }

    private void init()
    {
        mDrawPath = new Path();
        mBackgroundPaint = new Paint();
        initPaint();
    }

    private void initPaint()
    {
        mDrawPaint = new Paint();
        mDrawPaint.setColor(mPaintColor);
        mDrawPaint.setAntiAlias(true);
        mDrawPaint.setStrokeWidth(mStrokeWidth);
        mDrawPaint.setStyle(Paint.Style.STROKE);
        mDrawPaint.setStrokeJoin(Paint.Join.ROUND);
        mDrawPaint.setStrokeCap(Paint.Cap.ROUND);
    }

    private void drawBackground(Canvas canvas)
    {
        mBackgroundPaint.setColor(mBackgroundColor);
        mBackgroundPaint.setStyle(Paint.Style.FILL);
        canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), mBackgroundPaint);
    }

    private void drawPaths(Canvas canvas)
    {
        int i = 0;
        for (Path p : mPaths)
        {
            canvas.drawPath(p, mPaints.get(i));
            i++;
        }
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        drawBackground(canvas);
        drawPaths(canvas);

        canvas.drawPath(mDrawPath, mDrawPaint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);

        mCanvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

        mDrawCanvas = new Canvas(mCanvasBitmap);
    }

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

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                mDrawPath.reset();
                mDrawPath.moveTo(touchX, touchY);
                //mDrawPath.addCircle(touchX, touchY, mStrokeWidth/10, Path.Direction.CW);
                break;
            case MotionEvent.ACTION_MOVE:
                mDrawPath.lineTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_UP:
                mDrawPath.lineTo(touchX, touchY);
                mPaths.add(mDrawPath);
                mPaints.add(mDrawPaint);
                mDrawPath = new Path();
                initPaint();
                break;
            default:
                return false;
        }

        invalidate();
        return true;
    }

    public void setPaintColor(int color)
    {
        mPaintColor = color;
        mDrawPaint.setColor(mPaintColor);
    }

    public void setPaintStrokeWidth(int strokeWidth)
    {
        mStrokeWidth = strokeWidth;
        mDrawPaint.setStrokeWidth(mStrokeWidth);
    }

    public void setBackgroundColor(int color)
    {
        mBackgroundColor = color;
        mBackgroundPaint.setColor(mBackgroundColor);
        invalidate();
    }

    public Bitmap getBitmap()
    {
        drawBackground(mDrawCanvas);
        drawPaths(mDrawCanvas);
        return mCanvasBitmap;
    }

    public void undo()
    {
        if (mPaths.size() > 0)
        {
            mUndonePaths.add(mPaths.remove(mPaths.size() - 1));
            mUndonePaints.add(mPaints.remove(mPaints.size() - 1));
            invalidate();
        }else if (mLastPaths.size() > 0){
            for (Path p : mLastPaths){
                mPaths.add(p);
            }
            if (mLastPaints.size() > 0) {
                for (Paint p : mLastPaints) {
                    mPaints.add(p);
                }
            }
            invalidate();
        }
    }

    public void redo()
    {
        if (mUndonePaths.size() > 0)
        {
            mPaths.add(mUndonePaths.remove(mUndonePaths.size() - 1));
            mPaints.add(mUndonePaints.remove(mUndonePaints.size() - 1));
        }
        invalidate();
    }

    public void clearCanvas()
    {
        if (mPaths.size() > 0) {
            for (Path p : mPaths) {
                mLastPaths.add(p);
            }
            if (mPaints.size() > 0){
                for (Paint p : mPaints){
                    mLastPaints.add(p);
                }
            }
            //TODO: there is a bug relate with on touch move
            mDrawPath.reset();
            mPaths.clear();
            invalidate();
        }

        invalidate();
    }

    public void erase(boolean isEraseOn){
        if (isEraseOn){
            setPaintColor(Color.WHITE);
        }

    }


}

Screenshot

android
android-custom-view
asked on Stack Overflow Apr 7, 2020 by Rohit Kumar • edited Apr 7, 2020 by Rohit Kumar

1 Answer

0

There is a fix for your current code issue:

package co.ctdworld.sketchapp;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;

public class DrawingView extends View
{
    private Path mDrawPath;
    private Paint mBackgroundPaint;
    private Paint mDrawPaint;
    private Canvas mDrawCanvas;
    private Bitmap mCanvasBitmap;

    private ArrayList<Path> mPaths = new ArrayList<>();
    private ArrayList<Paint> mPaints = new ArrayList<>();
    private ArrayList<Path> mUndonePaths = new ArrayList<>();
    private ArrayList<Paint> mUndonePaints = new ArrayList<>();
    private ArrayList<Path> mLastPaths = new ArrayList<>();
    private ArrayList<Paint> mLastPaints = new ArrayList<>();

    // Set default values
    private int mBackgroundColor = 0xFFFFFFFF;
    private int mPaintColor = getContext().getResources().getColor(R.color.colorPrimaryDark);
    private int mStrokeWidth = 8;

    public DrawingView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init();
    }

    private void init()
    {
        mDrawPath = new Path();
        mBackgroundPaint = new Paint();
        initPaint();
    }

    private void initPaint()
    {
        mDrawPaint = new Paint();
        mDrawPaint.setColor(mPaintColor);
        mDrawPaint.setAntiAlias(true);
        mDrawPaint.setStrokeWidth(mStrokeWidth);
        mDrawPaint.setStyle(Paint.Style.STROKE);
        mDrawPaint.setStrokeJoin(Paint.Join.ROUND);
        mDrawPaint.setStrokeCap(Paint.Cap.ROUND);
    }

    private void drawBackground(Canvas canvas)
    {
        mBackgroundPaint.setColor(mBackgroundColor);
        mBackgroundPaint.setStyle(Paint.Style.FILL);
        canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), mBackgroundPaint);
    }

    private void drawPaths(Canvas canvas)
    {
        int i = 0;
        for (Path p : mPaths)
        {
            canvas.drawPath(p, mPaints.get(i));
            i++;
        }
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        drawBackground(canvas);
        drawPaths(canvas);

        canvas.drawPath(mDrawPath, mDrawPaint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);

        mCanvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

        mDrawCanvas = new Canvas(mCanvasBitmap);
    }

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

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                mDrawPath.reset();
                mDrawPath.moveTo(touchX, touchY);
                mUndonePaths.clear();
                //mDrawPath.addCircle(touchX, touchY, mStrokeWidth/10, Path.Direction.CW);
                break;
            case MotionEvent.ACTION_MOVE:
                mDrawPath.lineTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_UP:
                mDrawPath.lineTo(touchX, touchY);
                mPaths.add(mDrawPath);
                mPaints.add(mDrawPaint);
                mDrawPath = new Path();
                initPaint();
                break;
            default:
                return false;
        }

        invalidate();
        return true;
    }

    public void setPaintColor(int color)
    {
        mPaintColor = color;
        mDrawPaint.setColor(mPaintColor);
    }

    public void setPaintStrokeWidth(int strokeWidth)
    {
        mStrokeWidth = strokeWidth;
        mDrawPaint.setStrokeWidth(mStrokeWidth);
    }

    public void setBackgroundColor(int color)
    {
        mBackgroundColor = color;
        mBackgroundPaint.setColor(mBackgroundColor);
        invalidate();
    }

    public Bitmap getBitmap()
    {
        drawBackground(mDrawCanvas);
        drawPaths(mDrawCanvas);
        return mCanvasBitmap;
    }

    public void undo()
    {
        if (mPaths.size() > 0)
        {
            mUndonePaths.add(mPaths.remove(mPaths.size() - 1));
            mUndonePaints.add(mPaints.remove(mPaints.size() - 1));
            invalidate();
        }else if (mLastPaths.size() > 0){
            for (Path p : mLastPaths){
                mPaths.add(p);
            }
            if (mLastPaints.size() > 0) {
                for (Paint p : mLastPaints) {
                    mPaints.add(p);
                }
            }
            invalidate();
        }
    }

    public void redo()
    {
        if (mUndonePaths.size() > 0)
        {
            mPaths.add(mUndonePaths.remove(mUndonePaths.size() - 1));
            mPaints.add(mUndonePaints.remove(mUndonePaints.size() - 1));
        }
        invalidate();
    }

    public void clearCanvas()
    {
        //for only last deleted path
        mLastPaths.clear();
        mLastPaints.clear();

        if (mPaths.size() > 0) {
            for (Path p : mPaths) {
                mLastPaths.add(p);
            }
            if (mPaints.size() > 0){
                for (Paint p : mPaints){
                    mLastPaints.add(p);
                }
            }

            mPaths.clear();
            mPaints.clear();
            mUndonePaths.clear();
            mUndonePaints.clear();
            mDrawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
            invalidate();
        }
    }

}
answered on Stack Overflow Apr 7, 2020 by Rohit Kumar

User contributions licensed under CC BY-SA 3.0