我正在制作一个绘画应用程序,代码如下:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
setContentView(R.layout.coloring_activity3);
....
mv = (MyDrawView2) findViewById(R.id.drawerView);
mv.setDrawingCacheEnabled(true);
Constants.mPaint = new Paint();
Constants.mPaint.setAntiAlias(true);
Constants.mPaint.setDither(true);
Constants.mPaint.setColor(0xFF000000);
Constants.mPaint.setStyle(Paint.Style.STROKE);
Constants.mPaint.setStrokeJoin(Paint.Join.ROUND);
Constants.mPaint.setStrokeCap(Paint.Cap.ROUND);
Constants.mPaint.setStrokeWidth(Brush_size);
....
case R.id.btn_eraser:
Constants.mPaint.setXfermode(null);
Constants.mPaint.setAlpha(0xFF);
Constants.mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
layout_eraser_size.startAnimation(eraser_move_from_bottom_into_screen);
layout_eraser_size.setVisibility(View.VISIBLE);
btn_eraser.setEnabled(false);
break;
case R.id.btn_brush:
layout_brush_btns.startAnimation(brush_move_from_bottom_into_screen);
layout_brush_btns.setVisibility(View.VISIBLE);
btn_brush.setEnabled(false);
break;
case R.id.btn_undo:
Constants.custom_toast(this, "undo", "clicked");
mv.onClickUndo();
break;
public class MyDrawView2 extends View
{
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
Context context;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
public MyDrawView2(Context c, AttributeSet attrs)
{
super(c, attrs);
context = c;
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
setLayerType(View.LAYER_TYPE_SOFTWARE, null); // for solely removing the black eraser
}
@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
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, Constants.mPaint);
}
public void onClickUndo ()
{
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
invalidate();
}
else
{
Toast.makeText(getContext(), "nothing to undo", Toast.LENGTH_SHORT).show();
}
}
public void onClickRedo ()
{
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1)) ;
invalidate();
}
else
{
Toast.makeText(getContext(), "nothing to redo", Toast.LENGTH_SHORT).show();
}
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y)
{
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y)
{
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up()
{
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, Constants.mPaint); // commit the path to our offscreen
paths.add(mPath);
Toast.makeText(getContext(), "path added" + paths.size(), Toast.LENGTH_SHORT).show();
mPath.reset(); // kill this so we don't double draw
Constants.mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
// mPaint.setMaskFilter(null);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
touch_up
上的我添加了一个toast,计算了arraylist paths
中正确显示的路径数。但点击btn_undo
后,撤消功能无效。
怎么能修好?非常感谢!
答案 0 :(得分:1)
我通过对onSizeChanged(),onDraw()和touch_up()进行以下更改来完成撤消和重做:
public class MyDrawView2 extends View
{
private Canvas mCanvas;
private Path mPath;
Context context;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
public MyDrawView2(Context c, AttributeSet attrs)
{
super(c, attrs);
context = c;
mPath = new Path();
//added
mCanvas = new Canvas();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
//removed bitmap ...
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
//added
for (Path p : paths){
canvas.drawPath(p, Constants.mPaint);
}
canvas.drawPath(mPath, Constants.mPaint);
//removed bitmap ...
}
public void onClickUndo ()
{
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
invalidate();
}
else
{
Toast.makeText(getContext(), "nothing to undo", Toast.LENGTH_SHORT).show();
}
}
public void onClickRedo ()
{
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1)) ;
invalidate();
}
else
{
Toast.makeText(getContext(), "nothing to redo", Toast.LENGTH_SHORT).show();
}
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y)
{
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y)
{
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up()
{
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, Constants.mPaint); // commit the path to our offscreen
paths.add(mPath);
Toast.makeText(getContext(), "path added" + paths.size(), Toast.LENGTH_SHORT).show();
//added
mPath = new Path();
//removed reset...
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}