我正在创建一个利用以下DrawingSurfaceView类的绘图应用程序。在该类中,我有一个名为“erasePaint”的Paint,用户可以打开和关闭它。但相反,它只是画一条黑线。

当我将 Canvas 另存为透明png时,橡皮擦是正确的,但在屏幕上显示为黑色。

来自EraserPaint电话的屏幕截图,用于在Blob上写“Erik”



从 Canvas 上保存了PNG

橡​​皮擦油漆看起来像这样:

eraserPaint = new Paint();
        eraserPaint.setAlpha(0);
        eraserPaint.setColor(Color.TRANSPARENT);
        eraserPaint.setStrokeWidth(60);
        eraserPaint.setStyle(Style.STROKE);
        eraserPaint.setMaskFilter(null);
        eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        eraserPaint.setAntiAlias(true);

整个类(class)
     public KNDrawingSurfaceView(Context c, float width, float height, KNSketchBookActivity parent) {

        super(c);

        myWidth = width;
        myHeight = height;

        mBitmap = Bitmap.createBitmap((int) myWidth, (int) myHeight, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);

        _parent = parent;


        mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f);


        tile = new Paint();

        tileImage = BitmapFactory.decodeResource(getResources(), R.drawable.checkerpattern);
        shader = new BitmapShader(tileImage, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        tile.setShader(shader);


        mPath = new Path();
        eraserPaint = new Paint();
        eraserPaint.setAlpha(0x00);
        eraserPaint.setColor(Color.TRANSPARENT);
        eraserPaint.setStrokeWidth(60);
        eraserPaint.setStyle(Style.STROKE);
        //eraserPaint.setMaskFilter(null);
        eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        eraserPaint.setAntiAlias(true);

        mBitmapPaint = new Paint(Paint.DITHER_FLAG);



        mCanvas.drawRect(0, 0, myWidth, myHeight, tile);

        mCanvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
        mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

        super.onSizeChanged(w, h, oldw, oldh);


    }

    @Override
    protected void onDraw(Canvas canvas) {

        if (!_parent.isDrawerOpen()&&mPaint!=null) {
            Log.v("onDraw:", "curent paths size:" + paths.size());

            //mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            //canvas.drawPath(mPath, mPaint);
            for (int i=0;i< paths.size();i++) {
                tempPaint =  paints.get(i);
                eraserPaint.setStrokeWidth(tempPaint.getStrokeWidth());
                if(fills.get(i)){
                    tempPaint.setStyle(Style.FILL_AND_STROKE);
                    eraserPaint.setStyle(Style.FILL_AND_STROKE);
                }else{
                    tempPaint.setStyle(Style.STROKE);
                    eraserPaint.setStyle(Style.STROKE);
                }
                if(erasers.get(i)){
                    //tempPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
                    canvas.drawPath(paths.get(i), eraserPaint);
                }else{
                    //tempPaint.setXfermode(null);
                    canvas.drawPath(paths.get(i), tempPaint);
                }
                //canvas.drawPath(paths.get(i), tempPaint);
            }
            if(_parent.toggleFill.isChecked()){
               mPaint.setStyle(Style.FILL_AND_STROKE);
               eraserPaint.setStyle(Style.FILL_AND_STROKE);

            }else{
               mPaint.setStyle(Style.STROKE);
               eraserPaint.setStyle(Style.STROKE);
            }
            if(_parent.toggleErase.isChecked()){
               //mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
                 canvas.drawPath(mPath, eraserPaint);
            }else{
                //mPaint.setXfermode(null);
                canvas.drawPath(mPath, mPaint);
            }
            //canvas.drawPath(mPath, mPaint);
        }
    }

    public void onClickUndo() {

        if (paths.size() > 0) {
            undonePaths.add(paths.remove(paths.size() - 1));
            undonePaints.add(paints.remove(paints.size() - 1));
            undoneFills.add(fills.remove(fills.size() - 1));
            undoneErasers.add(erasers.remove(erasers.size() - 1));
            clearCanvasCache();
            invalidate();
        } else {

        }
        _parent.checkButtonStates();
    }

    public void onClickRedo() {

        if (undonePaths.size() > 0) {
            paths.add(undonePaths.remove(undonePaths.size() - 1));
            paints.add(undonePaints.remove(undonePaints.size() - 1));
            fills.add(undoneFills.remove(undoneFills.size() - 1));
            erasers.add(undoneErasers.remove(undoneErasers.size() - 1));
            clearCanvasCache();
            invalidate();
        } else {

        }
        _parent.checkButtonStates();
    }

    public void onClickClear() {

        paths.clear();
        paints.clear();
        fills.clear();
        erasers.clear();
        undoneFills.clear();
        undonePaths.clear();
        undonePaints.clear();
        undoneErasers.clear();
        clearCanvasCache();
        invalidate();
        _parent.checkButtonStates();
    }

    public void saveDrawing() {

        FileOutputStream outStream = null;
        String fileName = "tempTag";
        try {

            outStream = new FileOutputStream("/sdcard/" + fileName + ".png");

            mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
            outStream.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }

    }

    private float mX, mY;

    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {

        undonePaths.clear();
        undonePaints.clear();
        undoneFills.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);
        // commit the path to our offscreen
        if(_parent.toggleErase.isChecked()){
            mCanvas.drawPath(mPath, eraserPaint);
            erasers.add(true);
            paints.add(eraserPaint);
        }else{
            mCanvas.drawPath(mPath, mPaint);
            erasers.add(false);
            paints.add(mPaint);
        }

        // kill this so we don't double draw

        paths.add(mPath);


        if(_parent.toggleFill.isChecked()){
            fills.add(true);
        }else{
            fills.add(false);
        }
        if(_parent.toggleErase.isChecked()){
            erasers.add(true);
        }else{
            erasers.add(false);
        }


        _parent.checkButtonStates();
        mPath = new Path();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(mPaint==null &&!_parent._showingAlert){
            _parent.showNoPaintAlert();
        }

        if (!_parent.isDrawerOpen()&&mPaint!=null) {
            float x = event.getX();
            float y = event.getY();
            if (x > myWidth) {
                x = myWidth;

            }
            if (y > myHeight) {
                y = myHeight;

            }
            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;
        } else {
            return true;
        }
    }

    public void clearCanvasCache() {

        mBitmap = Bitmap.createBitmap((int) myWidth, (int) myHeight, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }
}

我应该补充一点,就是将这个“自定义 View ”添加到具有该方格图案作为背景图像的相对布局中。

请帮助。.我需要使用橡皮擦涂料后预览图像不显示黑色。.我需要它在后面显示方格图案。.我知道橡皮擦正在工作,因为那些黑色橡皮擦标记保存为透明的。

新注释

我在玩耍,发现了其他有趣的东西。实验中,我尝试从绘图切换到canvas,传递给onDraw方法,然后直接切换到我在名为mCanvas的构造器中设置的 Canvas ,并注意到它没有绘制到我能看到的程度。 onDraw像这样:
 protected void onDraw(Canvas canvas) {
       Log.v("DRAWING SURFACE", "canvas:"+canvas+" mCanvas:"+mCanvas);

吐出来
06-21 11:10:43.994: V/DRAWING SURFACE(4532): canvas:android.view.Surface$CompatibleCanvas@42a8c030 mCanvas:android.graphics.Canvas@431df180

最佳答案

我的应用程序也遇到了同样的问题。我什至尝试了“手指画”示例代码,但仍然遇到相同的问题。我从来没有能够将橡皮擦用作路径,但是我能够找到一种解决方法。当用户放下手指或发生“移动”事件时,我会画一个圆(可以是任何形状),而不是在擦除时画一条路径:

case MotionEvent.ACTION_DOWN:
mPaint.setStrokeWidth(25);
            mPaint.setXfermode(new PorterDuffXfermode(
                    PorterDuff.Mode.CLEAR));
            mCanvas.drawCircle(x, y, 10, mPaint);
            isErase = true;
            invalidate();
        }
        touch_start(x, y);
        invalidate();
        break;
case MotionEvent.ACTION_MOVE:
        if(isErase)
        {
            mCanvas.drawCircle(x, y, 20, mPaint);
        }
        else{
            touch_move(x, y);
        }invalidate();
        break;

将其合并到您的代码中将花费一些时间,但是我保证,与解决该问题所花费的时间相比,它所花费的时间更少。如果您认为有帮助的话,可以向我发送更多我的PaintView。

关于android - 尝试为 Canvas 创建橡皮擦颜料,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17197435/

10-12 05:45