Ich benutze obigen Code für rückgängig machen, aber Leinwand kann nicht durch den Aufruf dieser Methode aktualisieren. Ich habe erstellt DrawingView Klasse für Skizze Funktion i Undo wie für jede Funktionalität nur tun müssen, 1. smooth 2.Rectangle 3.Circle 4.Straight Linie usw.Innerhalb der Leinwand für Bildskizze rückgängig machen
public class DrawingView extends View {
protected Path mPath = new Path();
public static Paint mPaint;
protected Bitmap mBitmap;
public static Canvas mCanvas;
public int TOUCH_TOLERANCE = 5;
public static int lineThickness = 5;
public static int mCurrentShape;
public boolean isDrawing = false;
float mx,my,mStartX,mStartY;
private int stateToSave;
public static Paint mPaintErase = new Paint();
protected Path mPathErase = new Path();
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
public DrawingView(Context context) {
super(context);
init();
EraseLine();
}
public DrawingView(Context context,AttributeSet attrs)
{
super(context, attrs);
init();
EraseLine();
}
/**
* Create Path from Event.
* @param event
* @return
*/
private Path createPath(MotionEvent event) {
Path path = new Path();
// Save for ACTION_MOVE
this.mStartX = event.getX();
this.mStartY = event.getY();
path.moveTo(this.mStartX, this.mStartY);
return path;
}
protected void init()
{
mPaint = new Paint(Paint.DITHER_FLAG);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(getContext().getResources().getColor(R.color.colorYellow));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(lineThickness);
mPath = new Path();
paths.add(mPath);
}
public Bitmap getBitmap()
{
this.setDrawingCacheEnabled(true);
this.buildDrawingCache();
Bitmap bmp = Bitmap.createBitmap(this.getDrawingCache());
this.setDrawingCacheEnabled(false);
return bmp;
}
@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);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
mx = event.getX();
my = event.getY();
switch (mCurrentShape)
{
case 1:
onTouchEventSmoothLine(event);
break;
case 2:
onTouchEventErase(event);
break;
case 3:
onTouchEventLine(event);
break;
case 4:
onTouchEventCircle(event);
break;
case 5:
onTouchEventRectangle(event);
break;
case 6:
break;
default:
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
if (isDrawing)
{
switch (mCurrentShape)
{
case 1:
break;
case 2:
// EraseLine();
break;
case 3:
onDrawLine(canvas);
break;
case 4:
onDrawCircle(canvas);
break;
case 5:
onDrawRectangle(canvas);
break;
case 6:
onDrawSmoothLine(canvas);
break;
default:
break;
}
}
}
//------------------------------------------------------------------
// Rectangle
//------------------------------------------------------------------
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);
}
//------------------------------------------------------------------
// Circle
//------------------------------------------------------------------
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;
default:
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)
);
}
//------------------------------------------------------------------
// Line
//------------------------------------------------------------------
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;
}
}
//------------------------------------------------------------------
// Smooth Line
//------------------------------------------------------------------
private void onDrawSmoothLine(Canvas canvas)
{
for (Path p : paths)
{
canvas.drawPath(p, mPaint);
}
}
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();
paths.add(mPath);
invalidate();
break;
}
}
//------------------------------------------------------------------
// Erase Line
//------------------------------------------------------------------
public void EraseLine()
{
mPaintErase.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mPaintErase.setColor(Color.TRANSPARENT);
mPaintErase.setAntiAlias(true);
mPaintErase.setDither(true);
mPaintErase.setStyle(Paint.Style.STROKE);
mPaintErase.setStrokeJoin(Paint.Join.ROUND);
mPaintErase.setStrokeCap(Paint.Cap.ROUND);
mPaintErase.setStrokeWidth(lineThickness);
}
private void onTouchEventErase(MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
mPathErase.reset();
mPathErase.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) {
mPathErase.quadTo(mStartX, mStartY, (mx + mStartX)/2, (my + mStartY)/2);
mStartX = mx;
mStartY = my;
}
mCanvas.drawPath(mPathErase, mPaintErase);
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
mPathErase.lineTo(mStartX, mStartY);
mCanvas.drawPath(mPathErase, mPaintErase);
mPathErase.reset();
invalidate();
break;
}
}
/**
* Undo functionality.
*/
public void onClickUndo()
{
if (paths.size()>0)
{
paths.remove(paths.size()-1);
invalidate();
}
else
{
Toast.makeText(getContext().getApplicationContext(),"Undo not found.",Toast.LENGTH_SHORT).show();
}
//toast the user
}
@Override
public Parcelable onSaveInstanceState() {
//begin boilerplate code that allows parent classes to save state
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
//end
ss.stateToSave = this.stateToSave;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
//begin boilerplate code so parent classes can restore state
if(!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState)state;
super.onRestoreInstanceState(ss.getSuperState());
//end
this.stateToSave = ss.stateToSave;
}
static class SavedState extends BaseSavedState {
int stateToSave;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
this.stateToSave = in.readInt();
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(this.stateToSave);
}
//required field that makes Parcelables from a Parcel
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
was genau passiert? Code wird nicht ausgeführt? paths.size() ist immer 0? Error? bitte seien Sie klarer ... – Opiatefuchs
Ich habe gerade meinen Code bearbeitet und gebe Sichtklasse zum besseren Verständnis. Vielen Dank!!! –