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