Android:绘画应用中的撤消功能不起作用

时间:2014-10-26 03:47:10

标签: android path paint undo

我正在制作一个绘画应用程序,代码如下:

DrawActivity

protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
    setContentView(R.layout.coloring_activity3);
    ....

    mv = (MyDrawView2) findViewById(R.id.drawerView);   
    mv.setDrawingCacheEnabled(true);
    Constants.mPaint = new Paint();
    Constants.mPaint.setAntiAlias(true);
    Constants.mPaint.setDither(true);
    Constants.mPaint.setColor(0xFF000000);
    Constants.mPaint.setStyle(Paint.Style.STROKE);
    Constants.mPaint.setStrokeJoin(Paint.Join.ROUND);
    Constants.mPaint.setStrokeCap(Paint.Cap.ROUND);
    Constants.mPaint.setStrokeWidth(Brush_size);

    ....
    case R.id.btn_eraser:
        Constants.mPaint.setXfermode(null);
        Constants.mPaint.setAlpha(0xFF);
        Constants.mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        layout_eraser_size.startAnimation(eraser_move_from_bottom_into_screen);
        layout_eraser_size.setVisibility(View.VISIBLE); 
        btn_eraser.setEnabled(false);
        break;

    case R.id.btn_brush:
        layout_brush_btns.startAnimation(brush_move_from_bottom_into_screen);
        layout_brush_btns.setVisibility(View.VISIBLE); 
        btn_brush.setEnabled(false);
        break;

    case R.id.btn_undo:
        Constants.custom_toast(this, "undo", "clicked");
        mv.onClickUndo();
        break;

DrawView2

public class MyDrawView2 extends View 
{
    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint mBitmapPaint;
    Context context;

    private ArrayList<Path> paths = new ArrayList<Path>();
    private ArrayList<Path> undonePaths = new ArrayList<Path>(); 


    public MyDrawView2(Context c, AttributeSet attrs) 
    {
        super(c, attrs);
        context = c;
        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
        setLayerType(View.LAYER_TYPE_SOFTWARE, null); // for solely removing the black eraser
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) 
    {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) 
    {
        super.onDraw(canvas);
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
        canvas.drawPath(mPath, Constants.mPaint);
    }

    public void onClickUndo () 
    { 
        if (paths.size()>0) 
        { 
           undonePaths.add(paths.remove(paths.size()-1));
           invalidate();
        }
        else
        {
            Toast.makeText(getContext(), "nothing to undo", Toast.LENGTH_SHORT).show();  
        }     
    }

    public void onClickRedo ()
    {
       if (undonePaths.size()>0) 
       { 
           paths.add(undonePaths.remove(undonePaths.size()-1)) ;
           invalidate();
       } 
       else
       {
           Toast.makeText(getContext(), "nothing to redo", Toast.LENGTH_SHORT).show();  
       }

    }

    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);   
        mCanvas.drawPath(mPath, Constants.mPaint);  // commit the path to our offscreen
        paths.add(mPath);   
        Toast.makeText(getContext(), "path added" + paths.size(), Toast.LENGTH_SHORT).show();  
        mPath.reset();  // kill this so we don't double draw
        Constants.mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
        // mPaint.setMaskFilter(null);
    }

    @Override
    public boolean onTouchEvent(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;
    }
}

问题:

每个touch_up上的

我添加了一个toast,计算了arraylist paths中正确显示的路径数。但点击btn_undo后,撤消功能无效。

怎么能修好?非常感谢!

1 个答案:

答案 0 :(得分:1)

我通过对onSizeChanged(),onDraw()和touch_up()进行以下更改来完成撤消和重做:

public class MyDrawView2 extends View 
{

    private Canvas mCanvas;
    private Path mPath;

    Context context;

    private ArrayList<Path> paths = new ArrayList<Path>();
    private ArrayList<Path> undonePaths = new ArrayList<Path>(); 


    public MyDrawView2(Context c, AttributeSet attrs) 
    {
        super(c, attrs);
        context = c;
        mPath = new Path();
        //added
        mCanvas = new Canvas();

    }

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

    }

    @Override
    protected void onDraw(Canvas canvas) 
    {
        super.onDraw(canvas);
         //added
           for (Path p : paths){
               canvas.drawPath(p, Constants.mPaint);
           }


        canvas.drawPath(mPath, Constants.mPaint);

      //removed bitmap ...
    }

    public void onClickUndo () 
    { 
        if (paths.size()>0) 
        { 
           undonePaths.add(paths.remove(paths.size()-1));
           invalidate();
        }
        else
        {
            Toast.makeText(getContext(), "nothing to undo", Toast.LENGTH_SHORT).show();  
        }     
    }

    public void onClickRedo ()
    {
       if (undonePaths.size()>0) 
       { 
           paths.add(undonePaths.remove(undonePaths.size()-1)) ;
           invalidate();
       } 
       else
       {
           Toast.makeText(getContext(), "nothing to redo", Toast.LENGTH_SHORT).show();  
       }

    }

    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);   
            mCanvas.drawPath(mPath, Constants.mPaint);  // commit the path to our offscreen
            paths.add(mPath);   
            Toast.makeText(getContext(), "path added" + paths.size(), Toast.LENGTH_SHORT).show();  
            //added
            mPath = new Path();
            //removed reset...

        }

    @Override
    public boolean onTouchEvent(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;
    }
}
相关问题