android - 如何在 Canvas 绘画中实现 UNDO 功能后更改绘画颜色/描边

标签 android android-canvas

在我的画图应用程序中,我实现了 UNDO 功能,并且运行良好。但是,如果更改画笔颜色(或)画笔笔触,那么我之前绘制的所有路径都会更改为新的画笔颜色。代码如下:

public class CustomView extends View implements OnTouchListener {
    public Canvas mCanvas;
    private Path mPath;
    public Paint mPaint, mBitmapPaint;
    Bitmap mBitmap;
    Canvas canvas;
    public ArrayList<Path> paths = new ArrayList<Path>();
    public ArrayList<Path> undonePaths = new ArrayList<Path>();

    private Bitmap im;

    public CustomView(Context context) {
        super(context);
        setFocusable(true);
        setFocusableInTouchMode(true);
        setOnTouchListener(this);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(0xFFFFFFFF);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(6);
        mCanvas = new Canvas();
        mPath = new Path();

        im = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
        DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
        int w = metrics.widthPixels;
        int h = metrics.heightPixels;
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
        // mBitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
    }

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

    @Override
    protected void onDraw(Canvas canvas) {
        // mPath = new Path();
        // canvas.drawPath(mPath, mPaint);
        canvas.drawColor(Color.TRANSPARENT);
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
        for (Path p : paths) {
            canvas.drawPath(p, mPaint);
        }
        canvas.drawPath(mPath, mPaint);
    }

    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {
        undonePaths.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 >= TOUCH_TOLERANCE || dy >= 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
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        paths.add(mPath);
        mPath = new Path();

    }

    public void onClickUndo() {
        if (paths.size() > 0) {
            undonePaths.add(paths.remove(paths.size() - 1));
            invalidate();
        } else {

        }
        // toast the user
    }

    public void onClickRedo() {
        if (undonePaths.size() > 0) {
            paths.add(undonePaths.remove(undonePaths.size() - 1));
            invalidate();
        } else {

        }
        // toast the user
    }

    @Override
    public boolean onTouch(View arg0, MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

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

最佳答案

这是一个老问题,但我想为来到这里的任何人留下一个答案。解决方案是跟踪每个笔画的单独 Paint 实例(每个 Path 对象应该恰好有 1 个 Paint 对象)。

除了重置 mPath 之外,更改您的 touch_up 方法以重置 mPaint。

private void touch_up() {
    mPath.lineTo(mX, mY);
    mCanvas.drawPath(mPath, mPaint);
    paths.add(mPath);
    mPath = new Path();
    mPaints.add(mPaint)
    // Creates a new Paint reference, but keeps the previous state (color, width, etc.)
    mPaint = new Paint(mPaint);
}

然后你的 onDraw 方法看起来像这样。

for (int i = 0; i < mPaths.size(); i++) {
    canvas.drawPath(mPaths.get(i), mPaints.get(i));
}

关于android - 如何在 Canvas 绘画中实现 UNDO 功能后更改绘画颜色/描边,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12295542/

相关文章:

android - 每个设备上的速度和距离都不一样

java - 在 Android Canvas 上绘图不起作用

Android GCM - list 文件和注册

android - 获取 java.lang.OutOfMemoryError 异常?

android - textView 的 CSS 字体功能设置?

android - Canvas 上的可绘制图像

java - 如何在 Android Canvas 中创建颜色图案

java - 获取 Json 响应 Api

android - 使用android在sqlite数据库中插入和检索图像数据的问题

java - 动态绘制部分填充的圆