Android Canvas Redo and Undo Operation

后端 未结 3 520
心在旅途
心在旅途 2020-12-04 16:03

I am working on a drawing project. My code is working perfectly other than canvas redo and undo operations. My undo operation removes paths from the paths Arr

相关标签:
3条回答
  • 2020-12-04 16:40

    At first glance I see the following problems:

    • By adding your empty Path to paths as soon as you make it, you're going to have a problem as soon as you undo: you're popping that empty Path first, making the first undo not seem to work. Then if you draw into that Path, it's not added to paths. The solution is to add the completed Path to paths in touch_up() before creating a new one.

    That is, remove

    paths.add(mPath);
    

    from the constructor, and in touch_up(), change

    mPath = new Path();
    paths.add(mPath);
    

    to

    paths.add(mPath);
    mPath = new Path();
    

    You'll also want to add

    canvas.drawPath(mPath, mPaint);
    

    after your for loop in onDraw() in order to draw the in-progress Path.

    • You're not emptying undonePaths when the user starts drawing again.
    0 讨论(0)
  • 2020-12-04 16:40

    Problem

    The path is only shown when you finish drawing it which leaves the user clueless as to what he is drawing

    Solution

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    
       for (Path p : paths){
            canvas.drawPath(p, mPaint);
        }
    
        //Draw path along with the finger
        canvas.drawPath(mPath, mPaint);
    }
    

    Add canvas.drawPath(mPath,mPaint) to onDraw() so the user gets a feeling of actually painting on the canvas.

    0 讨论(0)
  • 2020-12-04 16:47

    Please check below code it is working..

    package com.testpath;
    
    import java.util.ArrayList;
    
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnTouchListener;
    import android.widget.Button;
    import android.widget.LinearLayout;
    
    public class TesUndoPaintActivity extends Activity {
        /** Called when the activity is first created. */
        LinearLayout linearLayout2;
        private ArrayList<Path> undonePaths = new ArrayList<Path>();
        private ArrayList<Path> paths = new ArrayList<Path>();
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            linearLayout2 = (LinearLayout) findViewById(R.id.linearLayout2);
            final DrawingPanel dp = new DrawingPanel(this);
            linearLayout2.addView(dp);
            ((Button) findViewById(R.id.button1))
                    .setOnClickListener(new OnClickListener() {
    
                        @Override
                        public void onClick(View v) {
                            // TODO Auto-generated method stub
                            if (paths.size() > 0) {
                                undonePaths.add(paths
                                        .remove(paths.size() - 1));
                                dp.invalidate();
                            }
                        }
                    });
            ((Button) findViewById(R.id.button2))
            .setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                     if (undonePaths.size()>0) { 
                           paths.add(undonePaths.remove(undonePaths.size()-1));
                           dp.invalidate();
                       } 
                }
            });
        }
    
        public class DrawingPanel extends View implements OnTouchListener {
    
            private Canvas mCanvas;
            private Path mPath;
            private Paint mPaint, circlePaint, outercirclePaint;
    
            // private ArrayList<Path> undonePaths = new ArrayList<Path>();
            private float xleft, xright, xtop, xbottom;
    
            public DrawingPanel(Context context) {
                super(context);
                setFocusable(true);
                setFocusableInTouchMode(true);
    
                this.setOnTouchListener(this);
    
                circlePaint = new Paint();
                mPaint = new Paint();
                outercirclePaint = new Paint();
                outercirclePaint.setAntiAlias(true);
                circlePaint.setAntiAlias(true);
                mPaint.setAntiAlias(true);
                mPaint.setColor(0xFFFFFFFF);
                outercirclePaint.setColor(0x44FFFFFF);
                circlePaint.setColor(0xAADD5522);
                outercirclePaint.setStyle(Paint.Style.STROKE);
                circlePaint.setStyle(Paint.Style.FILL);
                mPaint.setStyle(Paint.Style.STROKE);
                mPaint.setStrokeJoin(Paint.Join.ROUND);
                mPaint.setStrokeCap(Paint.Cap.ROUND);
                mPaint.setStrokeWidth(6);
                outercirclePaint.setStrokeWidth(6);
                mCanvas = new Canvas();
                mPath = new Path();
                paths.add(mPath);
            }
    
            public void colorChanged(int color) {
                mPaint.setColor(color);
            }
    
            @Override
            protected void onSizeChanged(int w, int h, int oldw, int oldh) {
                super.onSizeChanged(w, h, oldw, oldh);
            }
    
            @Override
            protected void onDraw(Canvas canvas) {
    
                for (Path p : paths) {
                    canvas.drawPath(p, mPaint);
                }
    
            }
    
            private float mX, mY;
            private static final float TOUCH_TOLERANCE = 0;
    
            private void touch_start(float x, float y) {
                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
                mPath = new Path();
                paths.add(mPath);
            }
    
            @Override
            public boolean onTouch(View arg0, MotionEvent event) {
                float x = event.getX();
                float y = event.getY();
    
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    // if (x <= cx+circleRadius+5 && x>= cx-circleRadius-5) {
                    // if (y<= cy+circleRadius+5 && cy>= cy-circleRadius-5){
                    // paths.clear();
                    // return true;
                    // }
                    // }
                    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;
            }
        }
    }
    

    And Below XML File.

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <LinearLayout
            android:id="@+id/linearLayout1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
    
            <Button
                android:id="@+id/button1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Undo" />
    
            <Button
                android:id="@+id/button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Redo" />
    
        </LinearLayout>
    
    
        <LinearLayout
            android:id="@+id/linearLayout2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >
    
        </LinearLayout>
    
    </LinearLayout>
    

    Please check it.

    0 讨论(0)
提交回复
热议问题