如何扩大 canvas 的绘图区域

how to expand drawing area of canvas

当用户使用 clearCanvas() 清除屏幕并按下 undo() 按钮然后 paint colorstroke-width 行为发生了变化。我该如何解决?现在我想在绘图区支持pdf文件也可以在上面绘制。

下面是我的自定义视图代码和截图:

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

您当前的代码问题已得到修复:

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();
        }
    }

}