我正在使用具有撤消/重做功能的绘画应用程序,并希望添加橡皮擦功能。
case R.id.undoBtn:
doodleView.onClickUndo();
break;
case R.id.redoBtn:
doodleView.onClickRedo();
break;
case R.id.eraserBtn:
Constants.mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); break;
// Drawing Part
private Bitmap mBitmap;
private Paint mBitmapPaint;
private Canvas mCanvas;
private Path mPath;
private int selectedColor = Color.BLACK;
private int selectedWidth = 5;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
private Map<Path, Integer> colorsMap = new HashMap<Path, Integer>();
private Map<Path, Integer> widthMap = new HashMap<Path, Integer>();
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
Context context_new;
public DoodleView(Context c, AttributeSet attrs)
{
super(c, attrs);
context_new = c;
setFocusable(true);
setFocusableInTouchMode(true);
setLayerType(View.LAYER_TYPE_SOFTWARE, null); // for solely removing the black eraser
mPath = new Path();
mCanvas = new Canvas();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
Constants.mPaint = new Paint();
Constants.mPaint.setAntiAlias(true); // smooth edges of drawn line
Constants.mPaint.setDither(true);
Constants.mPaint.setColor(Color.BLACK); // default color is black
Constants.mPaint.setStyle(Paint.Style.STROKE); // solid line
Constants.mPaint.setStrokeJoin(Paint.Join.ROUND);
Constants.mPaint.setStrokeWidth(20); // set the default line width
Constants.mPaint.setStrokeCap(Paint.Cap.ROUND); // rounded line ends
Constants.mPaint.setXfermode(null);
Constants.mPaint.setAlpha(0xFF);
}
@Override
public 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);
Constants.DRAW_W = w;
Constants.DRAW_H = h;
Log.d("TAG", "onSizeChanged!!!" + Constants.DRAW_W + Constants.DRAW_H + Constants.SCREEN_W + Constants.SCREEN_H);
// bitmap.eraseColor(Color.WHITE); // erase the BitMap with white
}
@Override
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(mBitmap, 0, 0, null); // draw the background screen
for (Path p : paths)
{
Constants.mPaint.setColor(colorsMap.get(p));
Constants.mPaint.setStrokeWidth(widthMap.get(p));
canvas.drawPath(p, Constants.mPaint);
}
Constants.mPaint.setColor(selectedColor);
Constants.mPaint.setStrokeWidth(selectedWidth);
canvas.drawPath(mPath, Constants.mPaint);
}
@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;
}
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;
startdrawing = true;
}
}
private void touch_up()
{
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, Constants.mPaint);
paths.add(mPath);
colorsMap.put(mPath,selectedColor);
widthMap.put(mPath,selectedWidth);
mPath = new Path();
}
public void onClickUndo()
{
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
invalidate();
}
else Toast.makeText(getContext(), R.string.toast_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(), R.string.toast_nothing_to_redo, Toast.LENGTH_SHORT).show();
}
public void setDrawingColor(int color)
{
selectedColor = color;
Constants.mPaint.setColor(color);
}
public int getDrawingColor()
{
return Constants.mPaint.getColor();
}
可以完美地执行正常绘画和撤消/重做。但是,橡皮擦不起作用。
按下(touch_start
)橡皮擦按钮并触摸屏幕后,所有先前绘制的线条立即变为黑色。
在touch_move
上使用橡皮擦时,橡皮擦本身正在绘制黑线,即使它处于CLEAR
模式。
在touch_up
后,所有其他绘制的线条保持黑色。 “擦除”区域也是黑色。但是,当随后绘制新路径时,原始线条变为其原始颜色,橡皮擦“擦除”的区域将其颜色变为所选的最后颜色,并且路径保留在视图中。
如何以正确的方式编写橡皮擦上的代码? (保持撤消/重做)
提前多多感谢!
答案 0 :(得分:0)
很难回答你的问题,但是。我按如下方式实现擦除功能:
擦除功能将通过简单的白色路径。因此擦除模式意味着您绘制的白色路径将比绘制路径宽。这样您甚至可以选择橡皮擦的宽度,撤消/重做功能将保持不变。
答案 1 :(得分:0)
试试这个解决方案 - 同样适用于undo / redo:
private float blur = 0F;
case R.id.eraserBtn:
Constants.mPaint.setColor(Color.WHITE); // or whatever color to match canvas color
Constants.mPaint.setShadowLayer(this.blur, 0F, 0F, Color.WHITE);
使用此解决方案,无需设置:
Constants.mPaint.setXfermode(null);
答案 2 :(得分:0)
答案 3 :(得分:0)
//请使用这是擦除概念。这是有效的。
public void addErasure(){
drawView.setErase(true);
drawView.setBrushSize(20);
}
public void addPencil(){
drawView.setErase(false);
drawView.setBrushSize(20);
drawView.setLastBrushSize(20);
}
/// this my drawing view. you can add this view into your main layout.
public class DrawingView extends View {
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
//brush sizes
private float brushSize, lastBrushSize;
//erase flag
private boolean erase=false;
private boolean isFirstTime = false;
public DrawingView(Context context, AttributeSet attrs){
super(context, attrs);
//setBackgroundColor(Color.CYAN);
setupDrawing();
}
//setup drawing
private void setupDrawing(){
//prepare for drawing and setup paint stroke properties
brushSize = getResources().getInteger(R.integer.medium_size);
lastBrushSize = brushSize;
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(brushSize);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
//canvasPaint.setColor(Color.GREEN);
}
//size assigned to view
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Bitmap canvasBackGroundBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
canvasBackGroundBitmap = getResizedBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.pop_up_big_bg),h,w);
// drawCanvas = new Canvas(canvasBackGroundBitmap);
// drawCanvas.drawColor(Color.GREEN);
setBackgroundDrawable(new BitmapDrawable(canvasBackGroundBitmap));
drawCanvas = new Canvas(canvasBitmap);
}
public static Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
//draw the view - will be called after touch event
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
//register user touches as drawing action
@Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
//respond to down, move and up events
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
//drawPath.lineTo(touchX, touchY);
//drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
default:
return false;
}
//redraw
invalidate();
return true;
}
//update color
public void setColor(String newColor){
invalidate();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
//set brush size
public void setBrushSize(float newSize){
float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
newSize, getResources().getDisplayMetrics());
brushSize=pixelAmount;
drawPaint.setStrokeWidth(brushSize);
}
//get and set last brush size
public void setLastBrushSize(float lastSize){
lastBrushSize=lastSize;
}
public float getLastBrushSize(){
return lastBrushSize;
}
//set erase true or false
public void setErase(boolean isErase){
erase=isErase;
if(erase) {
drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}else {
drawPaint.setXfermode(null);
}
}
//start new drawing
public void startNew(){
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
}