在 android 中撤消绘图 canvas

Undo in the drawing canvas in android

我在 android 中进行撤消操作。问题是,目前位图没有设置,我不能在上面画画。

这是我的代码,它是从扩展图像视图中提取的:

private ArrayList<Path> paths = new ArrayList<Path>();
private Path mPath;

public ScaleImageView(Context context) {
    super(context);
    sharedConstructing(context);
}

public void sharedConstructing(Context context) {
        super.setClickable(true);
        this.context = context;

        paint_bmp = new Paint();
        paint_line = new Paint();

        paint_line.setAntiAlias(true);
        paint_line.setStrokeWidth(width);
        paint_line.setColor(color);
        paint_line.setStyle(Paint.Style.STROKE);
        paint_line.setStrokeJoin(Paint.Join.ROUND);
        paint_line.setStrokeCap(Paint.Cap.ROUND);
        paint_line.setAlpha(alpha);

        drawListener = new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (getDrawable() != null) {
                    int action = event.getAction();
                    switch (action) {
                        case MotionEvent.ACTION_DOWN:
                            downx = getPointerCoords(event)[0];// event.getX();
                            downy = getPointerCoords(event)[1];// event.getY();
                            break;
                        case MotionEvent.ACTION_MOVE:
                            upx = getPointerCoords(event)[0];// event.getX();
                            upy = getPointerCoords(event)[1];// event.getY();
                            canvas.drawLine(downx, downy, upx, upy, paint_line);
                            mPath = new Path();
                            paths.add(mPath);
                            invalidate();
                            downx = upx;
                            downy = upy;
                            break;
                        case MotionEvent.ACTION_UP:
                            upx = getPointerCoords(event)[0];// event.getX();
                            upy = getPointerCoords(event)[1];// event.getY();
                            canvas.drawLine(downx, downy, upx, upy, paint_line);
                            mPath = new Path();
                            paths.add(mPath);
                            invalidate();
                            break;
                        case MotionEvent.ACTION_CANCEL:
                            break;
                        default:
                            break;
                    }
                }
                return true;
            }
        };

        setOnTouchListener(drawListener);
    }

//draw view start
    public void setNewImage(Bitmap alteredBitmap, Bitmap bmp) {
        canvas = new Canvas(alteredBitmap);
        matrix_draw = new Matrix();
        canvas.drawBitmap(bmp, matrix_draw, paint_bmp);
        setImageBitmap(alteredBitmap);
        mPath = new Path();
        paths.add(mPath);
    }

@Override
    protected void onDraw(Canvas canvas) {  
            for (Path p : paths){
                canvas.drawPath(p, paint_line);
            }
    }

    public void onClickUndo () {
        if (paths.size()>0){
            paths.remove(paths.size()-1);
            invalidate();
        }
    }

感谢您的帮助。

而不是删除路径,使用 Path.reset()。我给你一个class我拿来签名用的...

public class SignatureView extends View{
 signListner sListen;

 public SignatureView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  if (context instanceof signListner) {
   sListen = (signListner) context;
  }
  init(context);

 }

 public SignatureView(Context context, AttributeSet attrs) {
  super(context, attrs);
  if (context instanceof signListner) {
   sListen = (signListner) context;
  }
  init(context);
 }

 public SignatureView(Context context) {
  super(context);
  if (context instanceof signListner) {
   sListen = (signListner) context;
  }
  init(context);
 }

 Context mContext;
 private static final float STROKE_WIDTH = 5f;
 private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
 private Paint paint = new Paint();
 private Path path = new Path();

 private float lastTouchX;
 private float lastTouchY;
 private final RectF dirtyRect = new RectF();
 LinearLayout mContent;
 public static String tempDir;
 public int count = 1;
 public String current = null;
 private Bitmap mBitmap;
 View mView;

 private void init(Context context) {
  mContext = context;
  // LayoutInflater factory = LayoutInflater.from(context);
  /*
   * View myView = factory.inflate(R.layout.signature_view, null);
   * mContent = (LinearLayout) myView.findViewById(R.id.linearLayout);
   */
  paint.setAntiAlias(true);
  paint.setColor(Color.BLACK);
  paint.setStyle(Paint.Style.STROKE);
  paint.setStrokeJoin(Paint.Join.ROUND);
  paint.setStrokeWidth(STROKE_WIDTH);
 }

 public void save() {
  Log.v("log_tag", "Width: " + this.getWidth());
  Log.v("log_tag", "Height: " + this.getHeight());
  if (mBitmap == null) {
   mBitmap = Bitmap.createBitmap(this.getWidth(), this.getHeight(),
     Bitmap.Config.ARGB_8888);
  }
  Canvas canvas = new Canvas(mBitmap);
  try {
   String root = Environment.getExternalStorageDirectory().toString();
   File myDir = new File(root + "/GetImages");
   myDir.mkdirs();
   String fname = "Image-1001.jpg";
   File file = new File(myDir, fname);
   if (file.exists())
    file.delete();

   FileOutputStream mFileOutStream = new FileOutputStream(file);

   this.draw(canvas);
   mBitmap.compress(Bitmap.CompressFormat.PNG, 90, mFileOutStream);
   // mFileOutStream.flush();
   // mFileOutStream.close();
   String url = Images.Media.insertImage(
     mContext.getContentResolver(), mBitmap, "title", null);
   Log.v("log_tag", "url: " + url);

  } catch (Exception e) {
   Log.v("log_tag", e.toString());
  }
 }

 public void clear() {
  path.reset();
  invalidate();
 }

 @Override
 protected void onDraw(Canvas canvas) {
  canvas.drawPath(path, paint);
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  float eventX = event.getX();
  float eventY = event.getY();

  switch (event.getActionMasked()) {
  case MotionEvent.ACTION_DOWN:
   sListen.onSign(true);
   path.moveTo(eventX, eventY);
   lastTouchX = eventX;
   lastTouchY = eventY;
   return true;

  case MotionEvent.ACTION_MOVE:
   resetDirtyRect(eventX, eventY);
   int historySize = event.getHistorySize();
   for (int i = 0; i < historySize; i++) {
    float historicalX = event.getHistoricalX(i);
    float historicalY = event.getHistoricalY(i);
    expandDirtyRect(historicalX, historicalY);
    path.lineTo(historicalX, historicalY);
   }
   path.lineTo(eventX, eventY);
   break;

  case MotionEvent.ACTION_UP:
   sListen.onSign(false);
   resetDirtyRect(eventX, eventY);
   int historySize1 = event.getHistorySize();
   for (int i = 0; i < historySize1; i++) {
    float historicalX = event.getHistoricalX(i);
    float historicalY = event.getHistoricalY(i);
    expandDirtyRect(historicalX, historicalY);
    path.lineTo(historicalX, historicalY);
   }
   path.lineTo(eventX, eventY);
   break;
  /*case MotionEvent.ACTION_POINTER_UP:
   sListen.onSign(false);
   break;*/
  default:
   debug("Ignored touch event: " + event.toString());
   return false;
  }

  invalidate((int) (dirtyRect.left - HALF_STROKE_WIDTH),
    (int) (dirtyRect.top - HALF_STROKE_WIDTH),
    (int) (dirtyRect.right + HALF_STROKE_WIDTH),
    (int) (dirtyRect.bottom + HALF_STROKE_WIDTH));

  lastTouchX = eventX;
  lastTouchY = eventY;

  return true;
 }

 private void debug(String string) {
 }

 private void expandDirtyRect(float historicalX, float historicalY) {
  if (historicalX < dirtyRect.left) {
   dirtyRect.left = historicalX;
  } else if (historicalX > dirtyRect.right) {
   dirtyRect.right = historicalX;
  }

  if (historicalY < dirtyRect.top) {
   dirtyRect.top = historicalY;
  } else if (historicalY > dirtyRect.bottom) {
   dirtyRect.bottom = historicalY;
  }
 }

 private void resetDirtyRect(float eventX, float eventY) {
  dirtyRect.left = Math.min(lastTouchX, eventX);
  dirtyRect.right = Math.max(lastTouchX, eventX);
  dirtyRect.top = Math.min(lastTouchY, eventY);
  dirtyRect.bottom = Math.max(lastTouchY, eventY);
 }
 
 public boolean isEmpty(){
  return path.isEmpty();
 }
}

此处 clear() 正在清除 canvas。