我想创建类似绘图的项目,这是支持绘图,撤消,重做和橡皮擦所需的。橡皮擦必须仅删除图纸视图而不删除背景。下面的代码实现了撤消和重做功能。我想添加橡皮擦选项,但它没有完成。如何使用下面的代码实现橡皮擦选项?
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import java.util.ArrayList;
public class CanvasView extends View {
private Paint mPenPainter;
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
Context context;
private Paint mPaint;
private float mX, mY;
private static final float TOLERANCE = 5;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
private int paintColor = 0xFF000000;
public CanvasView(Context c, AttributeSet attrs) {
super(c, attrs);
context = c;
// we set a new Path
mPath = new Path();
// and we set a new Paint with the desired attributes
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(paintColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(4f);
//float mEraserWidth = getResources().getDimension(R.dimen.eraser_size);
mPenPainter = new Paint();
mPenPainter.setColor(Color.BLUE);
}
// override onSizeChanged
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// your Canvas will draw onto the defined Bitmap
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
// override onDraw
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw the mPath with the mPaint on the canvas when onDraw
for (Path p : paths) {
canvas.drawPath(p, mPaint);
}
canvas.drawPath(mPath, mPaint);
// paths.add(mPath);
}
private void startTouch(float x, float y) {
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
public void onClickUndo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
invalidate();
} else {
//Util.Imageview_undo_redum_Status=false;
}
//toast the user
}
public void onClickRedo() {
if (undonePaths.size() > 0) {
paths.add(undonePaths.remove(undonePaths.size() - 1));
invalidate();
} else {
// Util.Imageview_undo_redum_Status=false;
}
//toast the user
}
// when ACTION_MOVE move touch according to the x,y values
private void moveTouch(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOLERANCE || dy >= TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void upTouch() {
mPath.lineTo(mX, mY);
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
paths.add(mPath);
mPath = new Path();
}
//override the onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
float mCurX;
float mCurY;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mX = event.getX();
mY = event.getY();
startTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
invalidate();
break;
}
return true;
}
答案 0 :(得分:0)
我认为你应该使用这种模式: https://sourcemaking.com/design_patterns/command
我将它用于我的应用程序以使用undo / redo
答案 1 :(得分:0)
要删除,您需要找出当前选择和绘制路径之间的交叉。参考下面的代码
package opensourcecode.com.paginationwebview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
/**
* Created by damodhar.meshram on 4/26/2017.
*/
public class CanvasView extends View {
private Paint mPenPainter;
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
Context context;
private Paint mPaint;
private float mX, mY;
private static final float TOLERANCE = 5;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
private boolean isErasemode = false;
private int paintColor = 0xFF000000;
public CanvasView(Context c, AttributeSet attrs) {
super(c, attrs);
context = c;
// we set a new Path
mPath = new Path();
// and we set a new Paint with the desired attributes
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(paintColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(4f);
//float mEraserWidth = getResources().getDimension(R.dimen.eraser_size);
mPenPainter = new Paint();
mPenPainter.setColor(Color.BLUE);
}
public CanvasView(Context c) {
super(c);
context = c;
// we set a new Path
mPath = new Path();
// and we set a new Paint with the desired attributes
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(paintColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(4f);
//float mEraserWidth = getResources().getDimension(R.dimen.eraser_size);
mPenPainter = new Paint();
mPenPainter.setColor(Color.BLUE);
}
// override onSizeChanged
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// your Canvas will draw onto the defined Bitmap
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
// override onDraw
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw the mPath with the mPaint on the canvas when onDraw
for (Path p : paths) {
canvas.drawPath(p, mPaint);
}
canvas.drawPath(mPath, mPaint);
// paths.add(mPath);
}
private void startTouch(float x, float y) {
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
public void onClickUndo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
invalidate();
} else {
//Util.Imageview_undo_redum_Status=false;
}
//toast the user
}
public void onEraser(){
if(!isErasemode){
isErasemode = true;
}else{
isErasemode = false;
}
}
private void remove(int index){
paths.remove(index);
invalidate();
}
public void onClickRedo() {
if (undonePaths.size() > 0) {
paths.add(undonePaths.remove(undonePaths.size() - 1));
invalidate();
} else {
// Util.Imageview_undo_redum_Status=false;
}
//toast the user
}
// when ACTION_MOVE move touch according to the x,y values
private void moveTouch(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOLERANCE || dy >= TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void upTouch() {
mPath.lineTo(mX, mY);
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
paths.add(mPath);
mPath = new Path();
}
//override the onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
float mCurX;
float mCurY;
if(isErasemode){
for(int i = 0;i<paths.size();i++){
RectF r = new RectF();
Point pComp = new Point((int) (event.getX()), (int) (event.getY() ));
Path mPath = paths.get(i);
mPath.computeBounds(r, true);
if (r.contains(pComp.x, pComp.y)) {
Log.i("need to remove","need to remove");
remove(i);
break;
}
}
return false;
}else {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mX = event.getX();
mY = event.getY();
startTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
moveTouch(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
upTouch();
invalidate();
break;
}
return true;
}
}
}
答案 2 :(得分:0)
答案似乎有点晚,但经过两天的努力,我终于提出了解决方案。
public class DrawView extends View {
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mBitmapPaint;
Context context;
private Paint circlePaint;
private Path circlePath;
Boolean eraserOn = false;
Boolean newAdded = false;
Boolean allClear = false;
private Path drawPath;
private ArrayList<Bitmap> bitmap = new ArrayList<>();
private ArrayList<Bitmap> undoBitmap = new ArrayList<>();
public DrawView(Context c) {
super(c);
context=c;
drawPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
drawPaint = new Paint();
drawPaint.setAntiAlias(true);
drawPaint.setDither(true);
drawPaint.setColor(Color.BLACK);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
drawPaint.setStrokeWidth(20);
// drawPaint.setAlpha(80);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if(mBitmap==null) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// if(!eraserOn)
canvas.drawBitmap( mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(drawPath, drawPaint);
canvas.drawPath( circlePath, circlePaint);
}
public void onClickEraser(boolean isEraserOn)
{
if (isEraserOn) {
eraserOn = true;
drawPaint.setColor(getResources().getColor(android.R.color.transparent));
drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
else {
eraserOn = false;
drawPaint.setColor(mPaint.getColor());
drawPaint.setXfermode(null);
}
}
public void onClickUndo () {
if(newAdded) {
bitmap.add(mBitmap.copy(mBitmap.getConfig(), mBitmap.isMutable()));
newAdded=false;
}
if (bitmap.size()>1)
{
undoBitmap.add(bitmap.remove(bitmap.size()-1));
mBitmap= bitmap.get(bitmap.size()-1).copy(mBitmap.getConfig(),mBitmap.isMutable());
mCanvas = new Canvas(mBitmap);
invalidate();
if(bitmap.size()==1)
allClear=true;
}
else
{
}
//toast the user
}
public void onClickRedo (){
if (undoBitmap.size()>0)
{
bitmap.add(undoBitmap.remove(undoBitmap.size()-1));
mBitmap= bitmap.get(bitmap.size()-1).copy(mBitmap.getConfig(),mBitmap.isMutable());
mCanvas = new Canvas(mBitmap);
invalidate();
}
else
{
}
//toast the user
}
@Override
public boolean performClick() {
return super.performClick();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(penSelected || eraserSelected) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
newAdded = true;
if(!allClear)
bitmap.add(mBitmap.copy(mBitmap.getConfig(),mBitmap.isMutable()));
else allClear=false;
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
if (eraserOn) {
drawPath.lineTo(touchX, touchY);
mCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
drawPath.moveTo(touchX, touchY);
} else {
drawPath.lineTo(touchX, touchY);
}
break;
case MotionEvent.ACTION_UP:
mCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
case MotionEvent.ACTION_CANCEL:
return false;
default:
return false;
}
invalidate();
return true;
}
return false;
}
}