ПортерДафф.Режим.ЯСНО рисует черным на холсте

#android #android-canvas #paint

Вопрос:

Я хочу внедрить ластик в свое приложение для рисования. Но код

 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
 

рисует черную линию на холсте. Если я меняю цвет фона, холст тоже становится черным.

Я также пробовал использовать setLayerType (), но он рисует белый цвет на любом цветовом фоне.

 // In constructor
setLayerType(View.LAYER_TYPE_SOFTWARE, null); 
 

Ниже приведен код для моего PaintView.

 public class PaintView extends View {
    private Bitmap bitmapBackground,bitmapView;
    private int backgroundColor;
    private int brushSize;
    private int eraserSize;
    private float mX,mY;
    private Canvas canvas=null;
    private final int TOUCH_TOLERANCE=4;
    private int paintColor;

    private int modeStatus;
    /*
    1 for brush
    2 for eraser
    */
    
    private ArrayList<Paint> paints = new ArrayList<>();
    private ArrayList<Path> paths = new ArrayList<>();
    private int historyPointer=0;

    public PaintView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initialise();
    }

    private void initialise() {
        eraserSize=12;
        brushSize=12;
        backgroundColor= Color.WHITE;
        paintColor = Color.BLACK;
        modeStatus = 1;

        paints.add(createPaint());
        paths.add(new Path());
        historyPointer  ;
    }

    private float toPx(int brushSize) {
        return brushSize*(getResources().getDisplayMetrics().density);
    }

    public void init(int width,int height) {
        bitmapBackground=Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        bitmapView=Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        canvas=new Canvas(bitmapView);
    }

   
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawColor(backgroundColor);
        canvas.drawBitmap(bitmapBackground,0,0,null);

        for (int i=0;i<historyPointer;i  ) {
            Path path = paths.get(i);
            Paint paint = paints.get(i);

            canvas.drawPath(path,paint);
        }

    }

    private Paint createPaint() {
        Paint paint = new Paint();

        paint.setColor(paintColor);
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeJoin(Paint.Join.ROUND);

        if (modeStatus==1) {
            paint.setXfermode(null);
            paint.setShader(null);
            paint.setMaskFilter(null);
            paint.setStrokeWidth(toPx(brushSize));
        }
        else {
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
            paint.setStrokeWidth(toPx(eraserSize));
        }

        return paint;
    }

    private Path createPath(float x,float y) {
        Path path = new Path();
        path.moveTo(x,y);
        return path;
    }

    public void setBackgroundColor(int backgroundColor) {
        this.backgroundColor=backgroundColor;
        invalidate(); //Redraw
    }

    public void setBrushSize(int brushSize) {
        this.brushSize=brushSize;
        modeStatus=1;
    }

    public void setBrushColor(int color) {
        paintColor=color;
    }

    public void setEraserSize(int eraserSize) {
        this.eraserSize=eraserSize;
        modeStatus=2;
    }

    public int getBrushSize() {
        return this.brushSize;
    }

    public int getEraserSize() {
        return this.eraserSize;
    }

    private void updateHistory(Path path) {
        if (historyPointer==paths.size()) {
            paths.add(path);
            paints.add(createPaint());
            historyPointer  ;
        }
        else {
            // For undo and redo
            paths.set(historyPointer,path);
            paints.set(historyPointer,createPaint());
            historyPointer  ;

            for (int i=historyPointer,size=paths.size();i<size;i  ) {
                paths.remove(historyPointer);
                paints.remove(historyPointer);
            }
        }
    }

    private Path getCurrentPath() {
        return paths.get(historyPointer-1);
    }

    private Paint getCurrentPaint() {
        return paints.get(historyPointer-1);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            // Case when finger touches the screen
            case MotionEvent.ACTION_DOWN:
                touchStart(x,y);
                break;

            // Case when finger moves on screen
            case MotionEvent.ACTION_MOVE:
                touchMove(x,y);
                break;

            // Case when finger is taken away from screen
            case MotionEvent.ACTION_UP:
                touchUp();
                break;

            default :
                return false;
        }
        return true;
    }

    private void touchStart(float x, float y) {
        mX=x;
        mY=y;
        updateHistory(createPath(x,y));
    }

    private void touchMove(float x, float y) {
        float dx = Math.abs(x-mX);
        float dy = Math.abs(y-mY);

        Path path = getCurrentPath();

        if (dx>=TOUCH_TOLERANCE || dy>=TOUCH_TOLERANCE) {
            path.quadTo(x,y,(x mX)/2,(y mY)/2);
            mX=x;
            mY=y;
        }
        invalidate();;
    }

    private void touchUp() {
    }
}
 

Ответ №1:

Я получил ответ после многих исследований, и следующее сработало. Просто сохраните слой холста после установки цвета фона и, наконец, восстановите количество. Метод onDraw выглядит следующим образом —

 protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvas.drawColor(backgroundColor);
    canvas.drawBitmap(bitmapBackground,0,0,null);

    int layerId = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG);  // Line 1 added

    for (int i=0;i<historyPointer;i  ) {
        Path path = paths.get(i);
        Paint paint = paints.get(i);

        canvas.drawPath(path,paint);
    }

    canvas.restoreToCount(layerId); // Line 2 added
}