1

Before I start I would like you to tell that I am using a very improper method for the "undo" operation. I have a drawing app which will save each strokes you draw on the view, and when you exit the app the final image will be copied to a folder and others will be deleted.

Now when you draw strokes on the view, each file will be saved in a temp. folder and the path of each file will be inserted to the database, this is to implement the undo operation. When the user clicks for undo, the last inserted value(path) will be deleted and the next path will be quired. My plan is to use this path to draw the image on the view, so each time the user 'undo's , the last path saved in the database will be deleted and the next path will be taken.

Hope you got my idea..! Now my issue is , I am not able to draw the image to the view, I have a custom view which draws the stokes.

View

public class MyView extends View {

        private static final float MINP = 0.25f;
        private static final float MAXP = 0.75f;

        private Bitmap  mBitmap;

        private Paint   mBitmapPaint;

        public MyView(Context c) {
            super(c);


            mPath = new Path();
            mBitmapPaint = new Paint(Paint.DITHER_FLAG);

        }

        @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);
            mCanvas.drawColor(Color.BLACK);

         }

        @Override
        protected void onDraw(Canvas canvas) {

            try{

                 new SaveFileThread().execute(null);        //------->save strokes as files

                Log.i("In ondraw log", "Wow "+filename);

                if(undoflag=="undo" && nextp!="haha"){

                    String pat=UnDo();

                    if(pat!=null){

                        if(pat==filename){ pat=UnDo(); Log.i("undo called twice", "not again");}
                        else{

                        //  Bitmap nbmp=LoadBMPsdcard(pat);
                            //render the SD card image  
                      //      canvas.drawBitmap(nbmp, 0, 0, null);  

                        }
                    }
                    //the parent onDraw() method.  
                 //   super.onDraw(canvas);

                }


            //canvas.drawColor(000000);
            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
            canvas.drawPath(mPath, mPaint);

            }catch(Exception e){
                e.printStackTrace();
            }

        }

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

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

I have a thread that will do the saving, How can I draw an image from the SD card to this view.

Can any one suggest me any better ideas to do this. It would be a great help if you have some sample code if you bring a different idea.

Thanks in advance

Happy Coding

rahul
  • 2,758
  • 5
  • 32
  • 53

2 Answers2

0

This code is working in my drawing app..

private Slate mSlate;
private TiledBitmapCanvas mTiledCanvas;

 public void clickUndo(View unused) {

        mSlate.undo();
    }


public void undo() {
        if (mTiledCanvas == null) {
            Log.v(TAG, "undo before mTiledCanvas inited");
        }
        mTiledCanvas.step(-1);

        invalidate();
    }
Akshatha S R
  • 1,237
  • 1
  • 15
  • 30
0

Well, I would not store the bitmaps in files at all. If it's a simple drawing app, then you could (I would) just have an arrayList of say 20 Bitmaps and store the bitmaps to the list. If the length ever gets above 20, remove the first item. This will give you some undo buffer and allow you to more easily handle the operation. As for saving to the sd card look here.

~Aedon

Edit 1:

Use this method to create the bitmap of the canvas.

public Bitmap toBitmap(Canvas canvas) {
    Bitmap b = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
    canvas.setBitmap(b);
    draw(canvas);
    return b;
}

Sample onToushListener:

new OnTouchListener() {
    public void onTouch(View v, MotionEvent e) {
        switch(e.getAction()) {
            case MotionEvent.ACTION_DOWN: mIsGesturing = true; mCurrentDrawPath.moveTo(...); // Fall through
            case MotionEvent.ACTION_MOVE: // create the draw path the way you are now.
            case MotionEvent.ACTION_UP: mIsGesturing = false; addNewBufferBitmap(toBitmap(canvas)); break;
        }
    }
};

And onDraw(canvas) will look similar to this:

public void onDraw(Canvas canvas) {
    canvas.drawBitmap(getLastBufferBitmap(), 0, 0, null);
    if (mCurrentDrawPath != null) canvas.drawPath(mCurrentDrawPath, mPathPaint);
    if (mIsGesturing) mCanvas = canvas;
}
ahodder
  • 11,353
  • 14
  • 71
  • 114
  • hi , thanks for responding to my question, I think its a good suggestion to use a stack, but my doubt is how can i bring that bitmap from the canvas, each time the user clicks 'undo' ? – rahul May 13 '11 at 03:51
  • When you draw to the canvas, claim a bitmap of it. When the user clicks undo, the canvas will have to update. Just draw the last known bitmap (last in the list). – ahodder May 13 '11 at 16:01
  • ok...how can we update the canvas...by creating a new canvas object. like this--> mCanvas=new Canvas(bitmap); ? – rahul May 13 '11 at 17:38
  • Um, I really can't explain myself to well, so use the sample code in my answer to help you out on this. – ahodder May 13 '11 at 17:59