试图创造一个橡皮漆帆布帆布、橡皮、创造一个

2023-09-07 04:33:20 作者:桃花快开了吧

我创建一个绘图应用程序,使用下面的DrawingSurfaceView类。在这个类我称之为eraserPaint,用户可以打开和关闭。当上油漆是假设橡皮擦什么都在它的路径中的涂料。而是它只是一条黑色的分界线。

在我的画布上保存了作为一个透明的PNG橡皮擦是正确的,但在屏幕上它显示黑色..

截图从EraserPaint的手机用来写埃里克的BLOB

被救出来PNG从画布

eraserPaint看起来是这样的:

  eraserPaint =新的油漆();
        eraserPaint.setAlpha(0);
        eraserPaint.setColor(Color.TRANSPARENT);
        eraserPaint.setStrokeWidth(60);
        eraserPaint.setStyle(Style.STROKE);
        eraserPaint.setMaskFilter(空);
        eraserPaint.setXfermode(新PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        eraserPaint.setAntiAlias​​(真正的);
 

全班

 公共KNDrawingSurfaceView(上下文C,浮动幅度,浮动高度,KNSketchBookActivity父){

        超级(C);

        myWidth =宽度;
        myHeight =高度;

        mBitmap = Bitmap.createBitmap((INT)myWidth,(INT)myHeight,Bitmap.Config.ARGB_8888);
        mCanvas =新的Canvas(mBitmap);

        _parent =父母;


        mEmboss =新EmbossMaskFilter(新的浮动[] {1,1,1},0.4f,6,3.5F);


        瓦=新的油漆();

        tileImage = BitmapFactory.de codeResource(getResources(),R.drawable.checkerpattern);
        着色器=新BitmapShader(tileImage,Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
        tile.setShader(着色);


        的mpath =新路径();
        eraserPaint =新的油漆();
        eraserPaint.setAlpha(0×00);
        eraserPaint.setColor(Color.TRANSPARENT);
        eraserPaint.setStrokeWidth(60);
        eraserPaint.setStyle(Style.STROKE);
        //eraserPaint.setMaskFilter(null);
        eraserPaint.setXfermode(新PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        eraserPaint.setAntiAlias​​(真正的);

        mBitmapPaint =新的油漆(Paint.DITHER_FLAG);



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

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

    @覆盖
    保护无效onSizeChanged(INT W,INT小时,INT oldw,诠释oldh){

        super.onSizeChanged(W,H,oldw,oldh);


    }

    @覆盖
    保护无效的OnDraw(帆布油画){

        如果(_parent.isDrawerOpen()及!&安培;!mPaint = NULL){
            Log.v(OnDraw中:,个当前路径尺寸:+ paths.size());

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

            }其他{
               mPaint.setStyle(Style.STROKE);
               eraserPaint.setStyle(Style.STROKE);
            }
            如果(_parent.toggleErase.isChecked()){
               //mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
                 canvas.drawPath(的mpath,eraserPaint);
            }其他{
                //mPaint.setXfermode(null);
                canvas.drawPath(的mpath,mPaint);
            }
            //canvas.drawPath(mPath,mPaint);
        }
    }

    公共无效onClickUndo(){

        如果(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();
            无效();
        } 其他 {

        }
        _parent.checkButtonStates();
    }

    公共无效onClickRedo(){

        如果(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();
            无效();
        } 其他 {

        }
        _parent.checkButtonStates();
    }

    公共无效onClickClear(){

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

    公共无效saveDrawing(){

        FileOutputStream中outStream = NULL;
        字符串文件名=TempTag还可;
        尝试 {

            outStream =新的FileOutputStream(/ SD卡/+文件名+png格式);

            mBitmap.com preSS(Bitmap.Com pressFormat.PNG,100,outStream);
            outStream.close();

        }赶上(FileNotFoundException异常E){
            e.printStackTrace();
        }赶上(IOException异常E){
            e.printStackTrace();
        } 最后 {
        }

    }

    私人浮动MX,我的;

    私有静态最终浮动TOUCH_TOLERANCE = 4;

    私人无效touch_start(浮X,浮动Y){

        undonePaths.clear();
        undonePaints.clear();
        undoneFills.clear();
        mPath.reset();
        mPath.moveTo(X,Y);

        MX = X;
        我= Y;
    }

    私人无效TOUCH_MOVE(浮X,浮动Y){

        浮DX = Math.abs(X  -  MX);
        浮DY = Math.abs(Y  - 我的);
        如果(DX> = TOUCH_TOLERANCE || DY> = TOUCH_TOLERANCE){
            mPath.quadTo(MX,MY,(X + MX)/ 2,(Y +我)/ 2);
            MX = X;
            我= Y;
        }
    }

    私人无效touch_up(){

        mPath.lineTo(MX,MY);
        //提交路径,我们的屏幕外
        如果(_parent.toggleErase.isChecked()){
            mCanvas.drawPath(的mpath,eraserPaint);
            erasers.add(真正的);
            paints.add(eraserPaint);
        }其他{
            mCanvas.drawPath(的mpath,mPaint);
            erasers.add(假);
            paints.add(mPaint);
        }

        //杀了这个,所以我们不重复抽奖

        paths.add(的mpath);


        如果(_parent.toggleFill.isChecked()){
            fills.add(真正的);
        }其他{
            fills.add(假);
        }
        如果(_parent.toggleErase.isChecked()){
            erasers.add(真正的);
        }其他{
            erasers.add(假);
        }


        _parent.checkButtonStates();
        的mpath =新路径();
    }

    @覆盖
    公共布尔的onTouchEvent(MotionEvent事件){
        如果(mPaint == NULL和放大器;&安培;!_ parent._showingAlert){
            _parent.showNoPaintAlert();
        }

        如果(_parent.isDrawerOpen()及!&安培;!mPaint = NULL){
            浮X = event.getX();
            浮动Y = event.getY();
            如果(X> myWidth){
                X = myWidth;

            }
            如果(Y> myHeight){
                Y = myHeight;

            }
            开关(event.getAction()){
            案例MotionEvent.ACTION_DOWN:
                touch_start(X,Y​​);
                无效();
                打破;
            案例MotionEvent.ACTION_MOVE:
                TOUCH_MOVE(X,Y);
                无效();
                打破;
            案例MotionEvent.ACTION_UP:
                润色();
                无效();
                打破;
            }
            返回true;
        } 其他 {
            返回true;
        }
    }

    公共无效clearCanvasCache(){

        mBitmap = Bitmap.createBitmap((INT)myWidth,(INT)myHeight,Bitmap.Config.ARGB_8888);
        mCanvas =新的Canvas(mBitmap);
    }
}
 
墙面刷乳胶漆半个月不到到处出现裂痕 看师傅咋说

我要补充一点,我加入这个自定义视图到具有方格图案为背景图像相对布局。

请请请帮助..我需要一个preVIEW图像不显示黑色用橡皮擦漆后..我需要它背后显示的方格图案。我知道橡皮正在那些黑色的橡皮擦标记出保存为透明。

新笔记

我打得周围,发现了别的东西那是好奇。实验时,我试图从图纸到帆布切换被传递到的OnDraw 的方法,直接在画布上我设置在所谓的构造器 mCanvas ,发现它没有画,据我可以看到..所以我增加了一个日志到的OnDraw 像这样:

 保护无效的OnDraw(帆布油画){
       Log.v(绘图表面,帆布+帆布+mCanvas:+ mCanvas);
 

该吐出来的

  11月6号至21号:10:43.994:V /绘图表面(4532):帆布:android.view.Surface$CompatibleCanvas@42a8c030 mCanvas:android.graphics.Canvas@431df180
 

解决方案

我有这个同样的问题与我的应用程序。我甚至尝试了手指画例如code,仍然有同样的问题。我从来没有能够有橡皮擦工作路径,但我能找到一个解决办法。而不是绘画,当我删除的路径,我画一个圆(它可以是任何形状),当用户将手指向下或有一个移动事件:

 案例MotionEvent.ACTION_DOWN:
mPaint.setStrokeWidth(25);
            mPaint.setXfermode(新PorterDuffXfermode(
                    PorterDuff.Mode.CLEAR));
            mCanvas.drawCircle(X,Y,10,mPaint);
            isErase =真;
            无效();
        }
        touch_start(X,Y​​);
        无效();
        打破;
案例MotionEvent.ACTION_MOVE:
        如果(isErase)
        {
            mCanvas.drawCircle(X,Y,20,mPaint);
        }
        其他{
            TOUCH_MOVE(X,Y);
        }无效();
        打破;
 

这将需要一些时间将其纳入您的code,但我保证,你将花费更少的时间比你的时间已经花了试图解决这个问题的数额。如果你认为这将是有益的,我可以给你更多的我PaintView的。

I am creating a drawing app that utilizes the DrawingSurfaceView class below. In that class i have a Paint Called eraserPaint that the user can toggle on and off.. When on that paint is suppose to eraser what ever is in its path. but instead its just drawing a black line..

When i save out the canvas as a transparent png the eraser is correct but on the screen it shows black..

Screenshot from phone of EraserPaint used to write "Erik" on blob

Saved out PNG from canvas

eraserPaint looks like this:

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);

the WHOLE 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);
    }
}

I should add that i am adding this Custom View to a relative layout that has that checkered pattern as the background image..

PLEASE PLEASE PLEASE help.. i need that preview image to NOT show black after an eraser paint was used.. i need it to show the checkered pattern behind.. I know the eraser is working as those black eraser marks save out as transparent.

NEW NOTE

I was playing around and discovered something else thats curious. Experimenting, i tried switching from drawing to the canvas as passed to the onDraw method and directly to the canvas i set up in the contructor called mCanvas and noticed it did not draw as far as i could see.. so I added a log to the onDraw like so:

 protected void onDraw(Canvas canvas) {
       Log.v("DRAWING SURFACE", "canvas:"+canvas+" mCanvas:"+mCanvas);

which spits out

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

解决方案

I had this same problem with my app. I even tried the "finger paint" example code and still had the same problem. I was never able to have the eraser work as a path, but I was able to find a workaround. Rather than drawing a path when I erase, I draw a circle (It could be any shape) when the user puts his finger down or there is a "move" event:

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;

It will take some time to incorporate this into your code, but I guarantee you it will take less time than the amount of time you have already spent trying to fix this problem. I can send you more of my PaintView if you think it would be helpful.