사용자가 직사각형, 원형 등과 같은 도형을 그릴 수있는 그리기 응용 프로그램을 개발 중입니다. 사용자는 자유로운 손 그리기 (펜)도 만들 수 있습니다.캔버스에서 실행 취소 및 다시 실행
실행 취소, 다시 실행 기능을 추가하고 싶습니다. 검색 및 다시 실행 취소 및 다시 실행에 대한 대부분의 대답을 읽었지만 모든 경로와 관련이 있습니다. 두 개의 List를 관리하고 있다는 것을 의미합니다. 하나는 경로 목록으로 그려지며 다른 하나는 경로 목록을 실행 취소하기위한 목록입니다. 그것의 좋은 방법은 작동하지만 그 작업은 자유로운 드로잉이거나 경로로 작업하는 경우에만 작동합니다.
다른 모양의 캔버스 메서드를 여러 가지 형식으로 호출합니다.
캔버스 드로잉에 다시 실행 취소를 제공하는 데 도움을주세요.
여기에 내 코드
public class DrawingView extends android.support.v7.widget.AppCompatImageView {
public static final int RECTANGLE = 1;
public static final int SQUARE = 2;
public static final int CIRCLE = 3;
public
static final int LINE = 4;
public static final int SMOOTH_LINE = 5;
public static final int TRIANGLE = 6;
public static final int IMPORT_IMAGE = 7;
public static final int ERASER = 8;
private static final float TOUCH_TOLERANCE = 5;
private int color;
private int currentShape;
protected Paint mPaint;
protected Bitmap mBitmap;
protected Canvas mCanvas;
private float mx, my;
private float mStartX, mStartY;
private int width, height;
private boolean isDrawing = true;
public static int TOUCH_STROKE_WIDTH = 3;
public static int ERASER_WIDTH = 3;
private Path mPath = new Path();
int countTouch = 0;
float basexTriangle = 0;
float baseyTriangle = 0;
public DrawingView(Context context, int shape, int color) {
super(context);
initPaint();
}
protected void initPaint() {
color = DrawingActivity.selectedColor;
currentShape = DrawingActivity.currentShape;
mPaint = new Paint(Paint.DITHER_FLAG);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(color);
if (DrawingActivity.isFill && !DrawingActivity.isEraser && currentShape != SMOOTH_LINE) {
mPaint.setStyle(Paint.Style.FILL);
} else {
mPaint.setStyle(Paint.Style.STROKE);
}
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
if (DrawingActivity.isEraser) {
mPaint.setStrokeWidth(ERASER_WIDTH);
} else {
mPaint.setStrokeWidth(TOUCH_STROKE_WIDTH);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//Retrieve the point
mx = event.getX();
my = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initPaint();
break;
}
switch (currentShape) {
case RECTANGLE:
onTouchEventRectangle(event);
break;
case SQUARE:
onTouchEventSquare(event);
break;
case CIRCLE:
onTouchEventCircle(event);
break;
case LINE:
onTouchEventLine(event);
break;
case SMOOTH_LINE:
onTouchEventSmoothLine(event);
break;
case TRIANGLE:
onTouchEventTriangle(event);
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
if (isDrawing) {
switch (currentShape) {
case RECTANGLE:
onDrawRectangle(canvas);
break;
case SQUARE:
onDrawSquare(canvas);
break;
case CIRCLE:
onDrawCircle(canvas);
break;
case LINE:
onDrawLine(canvas);
break;
case SMOOTH_LINE:
onDrawLine(canvas);
break;
case TRIANGLE:
onDrawTriangle(canvas);
break;
}
}
//draw your element
}
private void onTouchEventRectangle(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
drawRectangle(mCanvas, mPaint);
invalidate();
break;
}
}
private void onDrawRectangle(Canvas canvas) {
drawRectangle(canvas, mPaint);
}
private void drawRectangle(Canvas canvas, Paint paint) {
float right = mStartX > mx ? mStartX : mx;
float left = mStartX > mx ? mx : mStartX;
float bottom = mStartY > my ? mStartY : my;
float top = mStartY > my ? my : mStartY;
canvas.drawRect(left, top, right, bottom, paint);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);
mCanvas = new Canvas(mBitmap);
}
private void onDrawSquare(Canvas canvas) {
onDrawRectangle(canvas);
}
private void onTouchEventSquare(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
adjustSquare(mx, my);
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
adjustSquare(mx, my);
drawRectangle(mCanvas, mPaint);
invalidate();
break;
}
}
/**
* Adjusts current coordinates to build a square
*
* @param x
* @param y
*/
protected void adjustSquare(float x, float y) {
float deltaX = Math.abs(mStartX - x);
float deltaY = Math.abs(mStartY - y);
float max = Math.max(deltaX, deltaY);
mx = mStartX - x < 0 ? mStartX + max : mStartX - max;
my = mStartY - y < 0 ? mStartY + max : mStartY - max;
}
private void onDrawCircle(Canvas canvas) {
canvas.drawCircle(mStartX, mStartY, calculateRadius(mStartX, mStartY, mx, my), mPaint);
}
private void onTouchEventCircle(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
mCanvas.drawCircle(mStartX, mStartY,
calculateRadius(mStartX, mStartY, mx, my), mPaint);
invalidate();
break;
}
}
/**
* @return
*/
protected float calculateRadius(float x1, float y1, float x2, float y2) {
return (float) Math.sqrt(
Math.pow(x1 - x2, 2) +
Math.pow(y1 - y2, 2)
);
}
private void onDrawLine(Canvas canvas) {
float dx = Math.abs(mx - mStartX);
float dy = Math.abs(my - mStartY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
canvas.drawLine(mStartX, mStartY, mx, my, mPaint);
}
}
private void onTouchEventLine(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
mCanvas.drawLine(mStartX, mStartY, mx, my, mPaint);
invalidate();
break;
}
}
private void onTouchEventSmoothLine(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
mPath.reset();
mPath.moveTo(mx, my);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
float dx = Math.abs(mx - mStartX);
float dy = Math.abs(my - mStartY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mStartX, mStartY, (mx + mStartX)/2, (my + mStartY)/2);
mStartX = mx;
mStartY = my;
}
mCanvas.drawPath(mPath, mPaint);
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
mPath.lineTo(mStartX, mStartY);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
invalidate();
break;
}
}
private void onDrawTriangle(Canvas canvas) {
if (countTouch < 3) {
canvas.drawLine(mStartX, mStartY, mx, my, mPaint);
} else if (countTouch == 3) {
canvas.drawLine(mx, my, mStartX, mStartY, mPaint);
canvas.drawLine(mx, my, basexTriangle, baseyTriangle, mPaint);
}
}
private void onTouchEventTriangle(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
countTouch++;
if (countTouch == 1) {
isDrawing = true;
mStartX = mx;
mStartY = my;
} else if (countTouch == 3) {
isDrawing = true;
}
invalidate();
break;
case MotionEvent.ACTION_MOVE:
invalidate();
break;
case MotionEvent.ACTION_UP:
countTouch++;
isDrawing = false;
if (countTouch < 3) {
basexTriangle = mx;
baseyTriangle = my;
mCanvas.drawLine(mStartX, mStartY, mx, my, mPaint);
} else if (countTouch >= 3) {
mCanvas.drawLine(mx, my, mStartX, mStartY, mPaint);
mCanvas.drawLine(mx, my, basexTriangle, baseyTriangle, mPaint);
countTouch = 0;
}
invalidate();
break;
}
}
public void clearDrawing()
{
setDrawingCacheEnabled(false);
onSizeChanged(width, height, width, height);
invalidate();
setDrawingCacheEnabled(true);
}
/**
* Getter of currentShape
*/
public int getCurrentShape() {
return currentShape;
}
/**
* Setter of currentShape
*/
public void setCurrentShape(int currentShape) {
this.currentShape = currentShape;
}
}
그리고 무엇 당신을 지적하는
희망 :
은 확실히 당신이 뭔가를 재실행을 수행 할 수 있도록 다른 목록에서 실행 취소 작업을 저장해야 문제 야? 도형을 취소 하시겠습니까? – CoolMind