Android canvas drawing undo/redo not working with background image

15 Views Asked by At

Canvas drwing success but can't undo or redo this drawing. i want to pin over the background image. it will be single pin draw or multiple pin or user can draw line. please helping for adding undo/redo this code. after drawing finish this image need to submit. here is my code.

`public class MainActivity extends Activity implements View.OnClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    drawableImageView = findViewById(R.id.ChoosenImageView);
    choosePicture = (Button) this.findViewById(R.id.ChoosePictureButton);
    savePicture = (Button) this.findViewById(R.id.SavePictureButton);
    imgEdited =  this.findViewById(R.id.imgEdited);
    btnRed =  this.findViewById(R.id.btnRed);
    btnGreen =  this.findViewById(R.id.btnGreen);
    btnBlue =  this.findViewById(R.id.btnBlue);
    btnUndo =  this.findViewById(R.id.btnUndo);
    btnRedo =  this.findViewById(R.id.btnRedo);

    customColor= Color.BLACK;
    Uri uri = Uri.parse("android.resource://com.tvl.qmsmg/drawable/shirt_icon");

    try {
        BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
        bmpFactoryOptions.inJustDecodeBounds = true;
        bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, bmpFactoryOptions);
        bmpFactoryOptions.inJustDecodeBounds = false;
        bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, bmpFactoryOptions);
        alteredBitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());
        drawableImageView.setNewImage(alteredBitmap, bmp, customColor, true);
    } catch (Exception e) {
        Log.v("ERROR", e.toString());
    }

    btnRed.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Log.d(TAG, "check_bitmap_uri_1: "+drawableImageView);
            customColor= Color.RED;
            colorChange(alteredBitmap, bmp, customColor);
        }
    });
    btnGreen.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            customColor= Color.GREEN;
            colorChange(alteredBitmap, bmp, customColor);
        }
    });
    btnBlue.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            customColor= Color.BLUE;
            colorChange(alteredBitmap, bmp, customColor);
        }
    });
    btnUndo.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            int result= drawableImageView.onClickUndo();
            if (result == 0){
                Toast.makeText(MainActivity.this, "no data found", Toast.LENGTH_SHORT).show();
            }
        }
    });
    btnRedo.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
           drawableImageView.onClickRedo();
        }
    });
    savePicture.setOnClickListener(this);
    choosePicture.setOnClickListener(this);
}

void colorChange(Bitmap alteredBitmap, Bitmap bmp, int changeColor){
    drawableImageView.setNewImage(alteredBitmap, bmp, changeColor, false);
}

}

public class DrawableImageView extends androidx.appcompat.widget.AppCompatImageView implements View.OnTouchListener {

float downx = 0;
float downy = 0;
float upx = 0;
float upy = 0;
float drawRadius;
Canvas canvas;
Paint paint;
Matrix matrix;

private Stack<Pair<Float, Float>> totalStack = new Stack<>();
private Stack<Pair<Float, Float>> undoStack = new Stack<>();
private Stack<Pair<Float, Float>> redoStack = new Stack<>();

private Canvas mCanvas;
private Path mPath;
private ArrayList<Path> pathList = new ArrayList<Path>();
private Paint mPaint;
private ArrayList<Path> undonePaths = new ArrayList<Path>();


public DrawableImageView(Context context) {
    super(context);
    setOnTouchListener(this);
    drawRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics());
}
public DrawableImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    setOnTouchListener(this);
    drawRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics());
}
public DrawableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    setOnTouchListener(this);
    drawRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics());
}

public void setNewImage(Bitmap alteredBitmap, Bitmap bmp, int color, boolean isFirst) {
    if (color == Color.WHITE){
        drawRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, getResources().getDisplayMetrics());
    } else {
        drawRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics());
    }
    paint = new Paint();
    paint.setColor(color);
    paint.setStrokeWidth(20);
    matrix = new Matrix();
    if (isFirst){
        canvas = new Canvas(alteredBitmap);
        canvas.drawBitmap(bmp, matrix, paint);
        setImageBitmap(alteredBitmap);
    }
  
}

public int onClickUndo () {
    if (!totalStack.isEmpty()) {
        redoStack.push(totalStack.peek());
        invalidate();
        return 1;
    } else {
        return 0;
    }
}

public void onClickRedo (){
    if (undonePaths.size()>0) {
        pathList.add(undonePaths.remove(undonePaths.size()-1));
        invalidate();
    }
}
@Override
public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            downx = getPointerCoords(event)[0];//event.getX();
            downy = getPointerCoords(event)[1];//event.getY();
            Log.d(TAG, "onTouch_ACTION_DOWN");
            break;
        case MotionEvent.ACTION_MOVE:
            upx = getPointerCoords(event)[0];//event.getX();
            upy = getPointerCoords(event)[1];//event.getY();
            totalStack.push(new Pair<>(upx, upy));
            canvas.drawCircle(totalStack.peek().first, totalStack.peek().second, drawRadius, paint);
            invalidate();
            downx = upx;
            downy = upy;
            Log.d(TAG, "onTouch_ACTION_MOVE: "+totalStack.size());
            break;
        case MotionEvent.ACTION_UP:
            upx = getPointerCoords(event)[0];//event.getX();
            upy = getPointerCoords(event)[1];//event.getY();
            /*canvas.drawLine(downx, downy, upx, upy, paint);
            canvas.drawCircle(upx, upy, drawRadius, paint);*/
            invalidate();
            Log.d(TAG, "onTouch_ACTION_UP");
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.d(TAG, "onTouch_ACTION_CANCEL");
            break;
        default:
            break;
    }
    return true;
}
final float[] getPointerCoords(MotionEvent e) {
    final int index = e.getActionIndex();
    final float[] coords = new float[] { e.getX(index), e.getY(index) };
    Matrix matrix = new Matrix();
    getImageMatrix().invert(matrix);
    matrix.postTranslate(getScrollX(), getScrollY());
    matrix.mapPoints(coords);
    return coords;
}

}

0

There are 0 best solutions below