Search code examples
androiddrawingandroid-canvasdraw

issue in redo undo operation in my paintview android


MainActivity.java

public class MainActivity extends Activity implements OnClickListener {

private DrawingView drawView;
int mColor;
String savedFilePath = "";
public static  ArrayList<Path> undonePaths = new ArrayList<Path>();
    public static  ArrayList<Path> paths = new ArrayList<Path>();
//buttons
Canvas bitmapCanvas;
RelativeLayout  mRelativeLayoutScreenShot;
static String mImagePath;
private ImageButton currPaint, drawBtn, eraseBtn, newBtn, saveBtn;
//sizes
private float smallBrush, mediumBrush, largeBrush;
ImageButton mImageViewPicklColor;
private boolean isFileAlreadySaved = false;

ImageButton mImageButtonList;
ImageButton mImageButtonShare;
File file;
Bitmap bitmap;
Button mButtonUNDo;
Dialog mDialogDate;
Button mButtonRedo;
boolean isStartAdl=false;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mDialogDate= new Dialog(MainActivity.this, android.R.style.Theme_NoTitleBar| android.R.style.Theme_Translucent|android.R.style.Theme_Holo_Dialog);
    mDialogDate.setCancelable(true);
    mDialogDate.requestWindowFeature(Window.FEATURE_NO_TITLE);
}


@Override
protected void onResume() {

    super.onResume();
    savedFilePath="";
      mColor = 0xff0000ff;




        //get drawing view
          mButtonUNDo=(Button)findViewById(R.id.btn_undo);
          mButtonRedo=(Button)findViewById(R.id.btn_redo);
        drawView = (DrawingView)findViewById(R.id.drawing);
        mImageViewPicklColor=(ImageButton)findViewById(R.id.pick_color);
        RelativeLayout paintLayout = (RelativeLayout)findViewById(R.id.paint_colors);
        mImageButtonShare=(ImageButton)findViewById(R.id.share);
        mImageButtonList=(ImageButton)findViewById(R.id.list);
        mRelativeLayoutScreenShot=(RelativeLayout)findViewById(R.id.rr_draw);
        mImageButtonList.setOnClickListener(this);
        //sizes from dimensions
        smallBrush = getResources().getInteger(R.integer.small_size);
        mediumBrush = getResources().getInteger(R.integer.medium_size);
        largeBrush = getResources().getInteger(R.integer.large_size);

        //draw button
        drawBtn = (ImageButton)findViewById(R.id.draw_btn);
        drawBtn.setOnClickListener(this);
        File direct = new File(Environment.getExternalStorageDirectory() + "/androidpaint");

        if(!direct.exists())
         {
             if(direct.mkdir());//directory is created;

         }
        mImagePath = Environment.getExternalStorageDirectory() + "/androidpaint";
        //set initial size
        drawView.setBrushSize(mediumBrush);

        //erase button
        eraseBtn = (ImageButton)findViewById(R.id.erase_btn);
        eraseBtn.setOnClickListener(this);

        //new button
        newBtn = (ImageButton)findViewById(R.id.new_btn);
        newBtn.setOnClickListener(this);

        //save button
        saveBtn = (ImageButton)findViewById(R.id.save_btn);
        saveBtn.setOnClickListener(this);
        mButtonRedo.setOnClickListener(this);
        mButtonUNDo.setOnClickListener(this);

        mImageViewPicklColor.setOnClickListener(this);
        mImageButtonShare.setOnClickListener(this);
        drawView.setErase(false);
        drawView.setBrushSize(drawView.getLastBrushSize());
        drawView.setColor(mColor);
        if (isStartAdl==true) {
            Intent intent = getIntent();
            finish();
            startActivity(intent);
        }


}

@Override
public void onClick(View view){


     if (view.getId()==R.id.btn_undo) {

        System.out.println("UNDO "+paths.size());
        if (paths.size() > 0) {
            undonePaths.add(paths
                    .remove(paths.size() - 1));
            drawView.invalidate();
        }
    }
     else  if (view.getId()==R.id.btn_redo) {
               if (undonePaths.size()>0) {
                   paths.add(undonePaths.remove(undonePaths.size()-1));
                    drawView.invalidate();
               }
      }

    });
}



}

DrawingView.java

public class DrawingView extends View {

  private float mX, mY;
  private static final float TOUCH_TOLERANCE = 0;
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
//brush sizes
private float brushSize, lastBrushSize;
//erase flag
private boolean erase=false;

public DrawingView(Context context, AttributeSet attrs){
    super(context, attrs);

    setupDrawing();
}

//setup drawing
private void setupDrawing(){

    //prepare for drawing and setup paint stroke properties
    brushSize = getResources().getInteger(R.integer.medium_size);
    lastBrushSize = brushSize;
    drawPath = new Path();
    drawPaint = new Paint();
    drawPaint.setColor(paintColor);
    drawPaint.setAntiAlias(true);
    drawPaint.setStrokeWidth(brushSize);
    drawPaint.setStyle(Paint.Style.STROKE);
    drawPaint.setStrokeJoin(Paint.Join.ROUND);
    drawPaint.setStrokeCap(Paint.Cap.ROUND);
    canvasPaint = new Paint(Paint.DITHER_FLAG);
    System.out.println("cadslfjds");
    MainActivity.paths.add(drawPath);
}

//size assigned to view
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    drawCanvas = new Canvas(canvasBitmap);
}

//draw the view - will be called after touch event
@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
    for (Path p : MainActivity.paths) {
        canvas.drawPath(p, drawPaint);
    }
    drawPaint.setColor(paintColor);
    canvas.drawPath(drawPath, drawPaint);

}

 private void touch_start(float x, float y) {
     drawPath.reset();
     drawPath.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) {
         drawPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
         mX = x;
         mY = y;
     }
 }

 private void touch_up() {
     drawPath.lineTo(mX, mY);
     // commit the path to our offscreen
     drawCanvas.drawPath(drawPath, drawPaint);
     // kill this so we don't double draw
     drawPath = new Path();
     MainActivity.paths.add(drawPath);
 }
   @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;
   }




public void setColor(int newColor){
    invalidate();
    paintColor = newColor;
    drawPaint.setColor(paintColor);
}

//set brush size
public void setBrushSize(float newSize){
    float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 
            newSize, getResources().getDisplayMetrics());
    brushSize=pixelAmount;
    drawPaint.setStrokeWidth(brushSize);
}

//get and set last brush size
public void setLastBrushSize(float lastSize){
    lastBrushSize=lastSize;
}
public float getLastBrushSize(){
    return lastBrushSize;
}

//set erase true or false
public void setErase(boolean isErase){
    erase=isErase;
    if(erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    else drawPaint.setXfermode(null);
}

//start new drawing
public void startNew(){
    drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    invalidate();
}

} when i run above code and click on UNDO and REDO button then UNDO Redo operation not perform any idea how can i solve it?

Second Issue

Color picker click event

   else if (view.getId()==R.id.pick_color) {
        LaunchColorPicker();
    }
        }

private void LaunchColorPicker(){
    int initialColor = 0xff0000ff;
    AmbilWarnaDialog dialog = new AmbilWarnaDialog(this, initialColor,  new OnAmbilWarnaListener() {
        public void onOk(AmbilWarnaDialog dialog, int color) {
                // color is the color selected by the user.
            mColor = color;
            drawView.setErase(false);
            drawView.setColor(mColor);
        }

        public void onCancel(AmbilWarnaDialog dialog) {
                // cancel was selected by the user
        }
    });

    dialog.show();
}

when i run colorpicker code and choose new color then my old painting view replace color with new color .

EDIT

public class DrawingView extends View {

private float mX, mY;
private static final float TOUCH_TOLERANCE = 0;
private Path drawPath;
private Paint drawPaint ;
private int paintColor = 0xFF660000,canvasPaint;
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private float brushSize, lastBrushSize;
private boolean erase=false;

public DrawingView(Context context, AttributeSet attrs){
    super(context, attrs);
    System.out.println("DrawingView");
    setupDrawing();
}

private void setupDrawing(){

    System.out.println("setupDrawing");
    brushSize = getResources().getInteger(R.integer.medium_size);
    lastBrushSize = brushSize;
    drawPath = new Path();
    drawPaint = new Paint();
    drawPaint.setAntiAlias(true);
    drawPaint.setStrokeWidth(brushSize);
    drawPaint.setStyle(Paint.Style.STROKE);
    drawPaint.setStrokeJoin(Paint.Join.ROUND);
    drawPaint.setStrokeCap(Paint.Cap.ROUND);
    System.out.println("cadslfjds");
    MainActivity.paths.add(drawPath);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    System.out.println("onSizeChanged");
    super.onSizeChanged(w, h, oldw, oldh);
    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    drawCanvas = new Canvas(canvasBitmap);
}

@Override
protected void onDraw(Canvas canvas) {
    System.out.println("onDraw");
    canvas.drawColor(canvasPaint);
    for ( ColoredPath  p: MainActivity.mColoredPaths) {
        drawPaint.setColor(p.getColor());
        canvas.drawPath(p.getPath(), drawPaint);
    }
    canvas.drawPath(drawPath, drawPaint);
    drawPaint.setColor(paintColor);
}

 private void touch_start(float x, float y) {
     drawPath.reset();
     drawPath.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) {
         drawPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
         mX = x;
         mY = y;
     }
 }

 private void touch_up() {
     drawPath.lineTo(mX, mY);
     drawCanvas.drawPath(drawPath, drawPaint);
     drawPath = new Path();
     MainActivity.paths.add(drawPath);
 }
   @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;
   }




public void setColor(int newColor){

    paintColor = newColor;
    drawPaint.setColor(paintColor);
     //     invalidate();
}

//set brush size
public void setBrushSize(float newSize){
    float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 
            newSize, getResources().getDisplayMetrics());
    brushSize=pixelAmount;
    drawPaint.setStrokeWidth(brushSize);
}

//get and set last brush size
public void setLastBrushSize(float lastSize){
    lastBrushSize=lastSize;
}
public float getLastBrushSize(){
    return lastBrushSize;
}

//set erase true or false
public void setErase(boolean isErase){
    erase=isErase;
    if(erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    else drawPaint.setXfermode(null);
}

//start new drawing
public void startNew(){
    drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    invalidate();
}
 }

ColoredPath.java public class ColoredPath {

private int color;
  private Path path;
public int getColor() {
    return color;
}
public void setColor(int color) {
    this.color = color;
}
public Path getPath() {
    return path;
}
public void setPath(Path path) {
    this.path = path;
}

} After edit my code when i draw line after completer ACTION_UP event whatever i draw it make whole clear my paint


Solution

  • Try removing canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint); and replace with canvas.drawColor(canvasPaint);

    If that works then the additional paths you see are on this background bitmap.

    Second issue, create a new storage class:

    public class ColoredPath{
      private int color;
      private Path path;
      //simple getters and setters here
    }
    

    Store like this:

    public static  ArrayList<ColoredPath> paths = new ArrayList<ColoredPath>();
    

    Use like this:

    for (ColouredPath p : MainActivity.paths) {
        drawPaint.setColor(p.getColor());
        canvas.drawPath(p.getPath(), drawPaint);
    }