Android:FingerPaint橡皮擦功能

Android:FingerPaint橡皮擦功能,android,path,paint,erase,Android,Path,Paint,Erase,我正在尝试在Android的Api演示中的Fingerpaint应用程序上实现擦除功能。我会根据自己的需要修改一些代码。起初,擦除功能运行良好。我用过: drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 在位图中绘制路径时,它工作良好。但是,当我实现Undo和Redo功能时(我实现它的方法是使用两个arraylist并在那里保存路径),PorterDuffXfermode不起作用。请看一下: 在图1中,

我正在尝试在Android的Api演示中的Fingerpaint应用程序上实现擦除功能。我会根据自己的需要修改一些代码。起初,擦除功能运行良好。我用过:

drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
在位图中绘制路径时,它工作良好。但是,当我实现Undo和Redo功能时(我实现它的方法是使用两个arraylist并在那里保存路径),PorterDuffXfermode不起作用。请看一下:

在图1中,我绘制了一些路径(存储在arraylist中,而不是在位图画布中绘制) 然后在2点,我按下了擦除图标。我不知道是什么原因导致所有的路都变黑了。然后在3点,我试图抹去我所做的路径(有人说它是黑色的)。然后当我切换回绘图模式。似乎它所做的只是画出另一条路,而不是抹去或抹去

有什么解决办法吗?还是变通办法? 下面是我的drawingClass的代码:

//this is where the drawing takes place
public class DrawingClass 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;
private float brushSize,lastBrushSize;
private boolean erase = false;
//array list for paths
private ArrayList<PathPoints> paths = new ArrayList<PathPoints>();
private ArrayList<PathPoints> undonePaths = new ArrayList<PathPoints>();

public Context context;


private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;


public DrawingClass(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
    this.context = context;
    setupDrawing();
}

private void setupDrawing(){
    setFocusable(true);
    setFocusableInTouchMode(true);

//instantiate the variable to get the last brush size
    brushSize = getResources().getInteger(R.integer.medium_size);
    lastBrushSize = brushSize;
//get drawing area setup for interaction
    drawCanvas = new Canvas();
    drawPath = new Path();
    drawPaint = new Paint();
    drawPaint.setColor(paintColor);
    //initial properties
    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);

    //paths.add(new PathPoints(drawPath, paintColor, brushSize));

}

public void setBrushSize(float newSize){
    //update brush size
    float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
            newSize, getResources().getDisplayMetrics());
    brushSize = pixelAmount;
    drawPaint.setStrokeWidth(brushSize);
    invalidate();
}

public void setLastBrushSize(float lastSize){
    //set the last brush size
    lastBrushSize = lastSize;
    invalidate();
}

public float getLastBrushSize(){
    //return the last brush size
    return lastBrushSize;
}

public void setErase(boolean isErase){
    //set erase true or false
    erase = isErase;
    if (erase) {
        //drawPaint.setColor(Color.WHITE);
        drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    }
    else drawPaint.setXfermode(null);
}

public void startNew(){
    //creates a new canvass
    drawCanvas.drawColor(0,PorterDuff.Mode.CLEAR);
    drawCanvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
    setDrawingCacheEnabled(true);
    String imgSaved = MediaStore.Images.Media.insertImage(
          context.getContentResolver(), getDrawingCache(),
            UUID.randomUUID().toString()+".png", "drawing");
    destroyDrawingCache();
    paths.clear();
    undonePaths.clear();
    invalidate();
}

@Override
protected void onSizeChanged(int w,int h,int oldw,int oldh){
    //view given size
    super.onSizeChanged(w, h, oldw, oldh);
    canvasBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
    drawCanvas = new Canvas(canvasBitmap);
}

@Override
protected void onDraw(Canvas canvas){
    //draw view
    //save the strokes in the bitmap
    //canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);

    for (PathPoints p : paths){
        drawPaint.setColor(p.getColor());
        drawPaint.setStrokeWidth(p.getBrush());
        invalidate();
        canvas.drawPath(p.getPath(), drawPaint);
    }
}

private void touch_start(float x, float y){
    drawPath.reset();
    drawPath.moveTo(x, (float) (y+.1));
    drawPath.lineTo(x, y);
    drawPath.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) {
            drawPath.quadTo(mX, mY, (x + mX)/2, (y+ mY)/2);
            mX = x;
            mY = y;
        }
}

private void touch_up(){
    drawPath.lineTo(mX, mY);
    drawCanvas.drawPath(drawPath, drawPaint);
    drawPath = new Path();
    paths.add(new PathPoints(drawPath, paintColor, brushSize));
}

@Override
public boolean onTouchEvent(MotionEvent event){
    //detect user touch
    float touchX = event.getX();
    float touchY = event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        invalidate();
        touch_start(touchX, touchY);
        break;
    case MotionEvent.ACTION_MOVE:
        invalidate();
        touch_move(touchX, touchY);
        break;
    case MotionEvent.ACTION_UP:
        invalidate();
        touch_up();
        drawPath.reset();
        break;
    default:
        return false;
    }
    invalidate();
    return true;
}

public void undoPath(){
    if (paths.size()>0) {
        undonePaths.add(paths.remove(paths.size()-1));
    } else {
        Log.d("Undo", "No paths left");
    }
    invalidate();
}

public void redoPath(){
    if (undonePaths.size()>0) {
        paths.add(undonePaths.remove(undonePaths.size()-1));
    } else {
        Log.d("Redo", "No paths left");
    }
    invalidate();
}


public void setColor(String newColor){
    //set color
    paintColor = Color.parseColor(newColor);
    drawPaint.setColor(paintColor);
    invalidate();
}

class PathPoints{
    private Path path;
    private int color;
    private float brushsize;
    private int x, y;

    //holds the paths data
    public PathPoints(Path path, int color, float brushsize) {
        this.path = path;
        this.color = color;
        this.brushsize = brushsize;
    }

    public Path getPath() {
        return path;
    }

    public void setPath(Path path) {
        this.path = path;
    }

    public float getBrush(){
        return brushsize;
    }

    public void setBrush(float brushsize){
        this.brushsize = brushsize;
    }

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

}

}
//这是绘图的地方
公共类DrawingClass扩展视图{
//绘图路径
专用路径;
//绘画和油画
私人油漆拉丝漆、帆布漆;
//原色
私有int paintColor=0xFF660000;
//帆布
私人帆布;
//画布位图
私有位图画布位图;
私人浮动笔刷大小,lastBrushSize;
私有布尔擦除=假;
//路径的数组列表
私有ArrayList路径=新ArrayList();
private ArrayList undonePaths=new ArrayList();
公共语境;
私人浮动mX,我的;
专用静态最终浮动接触公差=4;
公共绘图类(上下文、属性集属性){
超级(上下文,attrs);
//TODO自动生成的构造函数存根
this.context=上下文;
设置绘图();
}
专用图纸(){
设置聚焦(真);
setFocusableInTouchMode(真);
//实例化变量以获取最后一个笔刷大小
brushSize=getResources().getInteger(R.integer.medium\u size);
lastBrushSize=笔刷大小;
//获取用于交互的绘图区域设置
drawCanvas=新画布();
drawPath=新路径();
drawPaint=新油漆();
drawPaint.setColor(paintColor);
//初始属性
drawPaint.setAntiAlias(真);
drawPaint.设置行程宽度(刷号);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(绘制.连接.圆形);
drawPaint.setStrokeCap(油漆盖圆形);
画布绘制=新绘制(绘制抖动标志);
//添加(新路径点(drawPath、paintColor、brushSize));
}
公共大小(浮动新闻大小){
//更新笔刷大小
浮点像素数量=类型值。应用尺寸(类型值。复杂单位),
newSize,getResources().getDisplayMetrics());
笔刷大小=像素数量;
drawPaint.设置行程宽度(刷号);
使无效();
}
公共空白setLastBrushSize(浮动lastSize){
//设置最后一个笔刷大小
lastBrushSize=lastSize;
使无效();
}
公共浮点getLastBrushSize(){
//返回最后一个笔刷大小
返回最后一个笔刷大小;
}
公共void setErase(布尔isErase){
//将擦除设置为真或假
擦除=iSeries;
如果(删除){
//drawPaint.setColor(颜色:白色);
setXfermode(新的PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
else drawPaint.setXfermode(null);
}
公共无效startNew(){
//创建新画布
drawCanvas.drawColor(0,PorterDuff.Mode.CLEAR);
drawCanvas.drawBitmap(canvasBitmap,0,0,canvasPaint);
setDrawingCacheEnabled(真);
字符串imgSaved=MediaStore.Images.Media.insertImage(
context.getContentResolver(),getDrawingCache(),
UUID.randomUUID().toString()+“.png”,“drawing”);
销毁DrawingCache();
清除路径();
撤销海王星。清除();
使无效();
}
@凌驾
已更改尺寸的受保护空心(整数w、整数h、整数oldw、整数oldh){
//查看给定的大小
super.onSizeChanged(w,h,oldw,oldh);
canvasBitmap=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
drawCanvas=新画布(画布位图);
}
@凌驾
受保护的void onDraw(画布){
//绘图视图
//在位图中保存笔划
//drawBitmap(canvasBitmap,0,0,canvasPaint);
对于(路径点p:路径){
setColor(p.getColor());
drawPaint.setStrokeWidth(p.getBrush());
使无效();
drawPath(p.getPath(),drawPaint);
}
}
专用无效触摸启动(浮动x、浮动y){
drawPath.reset();
移动到(x,(浮动)(y+1));
绘制路径。线条到(x,y);
绘制路径。移动到(x,y);
mX=x;
mY=y;
}
私有无效触摸移动(浮动x、浮动y){
float dx=Math.abs(x-mX);
float dy=Math.abs(y-mY);
如果(dx>=接触公差| | dy>=接触公差){
drawPath.quadTo(mX,mY,(x+mX)/2,(y+mY)/2);
mX=x;
mY=y;
}
}
私人空间修补(){
drawPath.lineTo(mX,mY);
drawCanvas.drawPath(drawPath,drawPaint);
drawPath=新路径();
添加(新路径点(drawPath、paintColor、brushSize));
}
@凌驾
公共布尔onTouchEvent(运动事件){
//检测用户触摸
float touchX=event.getX();
float touchY=event.getY();
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:
使无效();
触摸启动(触摸X,触摸Y);
打破
case MotionEvent.ACTION\u移动:
使无效();
触摸移动(触摸X,触摸Y);
打破
case MotionEvent.ACTION\u UP:
使无效();
润色;
drawPath.reset();
打破
违约:
返回false;
}
使无效();
返回true;
}
公共路径(){
if(path.size()>0){
undonePaths.add(path.remove(path.size()-1));
}否则{
Log.d(“撤消”,“没有剩余路径”);
}
使无效();
}
公共路径(){
如果(撤消路径大小()>0){
add(undonePaths.remove(undonePaths.size()-1));
}否则{
Log.d(“重做”,“没有剩余路径”);
}
使无效();
}
公众的