Android, canvas: How do I clear (delete contents of) a canvas (= bitmaps), living in a surfaceView?
Asked Answered
B

21

111

In order to make a simple game, I used a template that draws a canvas with bitmaps like this:

private void doDraw(Canvas canvas) {
    for (int i=0;i<8;i++)
        for (int j=0;j<9;j++)
            for (int k=0;k<7;k++)   {
    canvas.drawBitmap(mBits[allBits[i][j][k]], i*50 -k*7, j*50 -k*7, null); } }

(The canvas is defined in "run()" / the SurfaceView lives in a GameThread.)

My first question is how do I clear (or redraw) the whole canvas for a new layout?
Second, how can I update just a part of the screen?

// This is the routine that calls "doDraw":
public void run() {
    while (mRun) {
        Canvas c = null;
        try {
            c = mSurfaceHolder.lockCanvas(null);
            synchronized (mSurfaceHolder) {
                if (mMode == STATE_RUNNING) 
                    updateGame();
                doDraw(c);          }
        } finally {
            if (c != null) {
                mSurfaceHolder.unlockCanvasAndPost(c);  }   }   }       }
Bandit answered 20/4, 2011 at 11:19 Comment(0)
E
84

How do I clear (or redraw) the WHOLE canvas for a new layout (= try at the game) ?

Just call Canvas.drawColor(Color.BLACK), or whatever color you want to clear your Canvas with.

And: how can I update just a part of the screen ?

There is no such method that just update a "part of the screen" since Android OS is redrawing every pixel when updating the screen. But, when you're not clearing old drawings on your Canvas, the old drawings are still on the surface and that is probably one way to "update just a part" of the screen.

So, if you want to "update a part of the screen", just avoid calling Canvas.drawColor() method.

Euphemie answered 20/4, 2011 at 12:1 Comment(15)
No, if you do not draw every pixel in the surface you will get very strange results (because double buffering is achieved by swapping pointers, so in the parts where you are not drawing you will not see what was there just before). You have to redraw every pixel of the surface at each iteration.Naos
@Guillaume Brunerie: What you just described has absolutely nothing to do with what I wrote in my answer. The Canvas mechanism keeps old drawings if we're not clearing it with a different bitmap or color. That is theoreticlly correct and it is practically true.Euphemie
@Viktor Lannér: I tried your solution and the background is drawn anew. But all bitmaps called by "canvas. drawBitmap" from my array mBits[..] are STILL there. How can I get rid of these?Bandit
@Viktor Lannér: If you call mSurfaceHolder.unlockCanvasAndPost(c) and then c = mSurfaceHolder.lockCanvas(null), then the new c does not contain the same thing as the previous c. You can’t update just a part of a SurfaceView, which is what the OP was asking I guess.Naos
@samClem: That depends in which situation you're drawing your bitmaps. If you want to get rid of them, just clear the Canvas once more.Euphemie
@Guillaume Brunerie: True, but not all. You can't update a part of the screen, as I wrote. But you can keep old drawings on the screen, which will have the effect of just "update a part of the screen". Try it yourself in a sample application. Canvas keeps old drawings.Euphemie
SHAME ON ME !!! I did initialize my array only ONCE at game start NOT at the consecutive re-starts - so ALL OLD pieces remained "onscreen" - they were just drawn anew !!! I AM VERY SORRY for my "dumbness"! Thanks to both of you !!!Bandit
@Viktor Lannér: I just wrote a little activity which draw a new bitmap in the SurfaceView every second, and the behaviour is the one I’m describing. I can clearly see that there are two buffers, and that you are not always writing to the same buffer. I can post the code as a new answer if you want.Naos
@Guillaume Brunerie: Nope, it's fine since I have my own Live Wallpaper based on a Canvas, which is telling me the opposite behaviour. Of course you can post it for other visitors here, it is good to have multiple answers as we can inspect each others solutions.Euphemie
Then this is probably because Live wallpapers do not work the same way as a regular SurfaceView. Anyway, @samClem: always redraw every pixel of the Canvas at each frame (as stated in the doc) or you will have strange flickering.Naos
@Guillaume Brunerie: Well, that's not correct either. Live Wallpapers has the same SurfaceView as a regular application. Also, I have seen the same thing on one of my regular applications which have a SurfaceView. But as I said, post your answer so other can see what you're meaning.Euphemie
Let's not forget the possibility of the dirty rectangle that can be passed to lockCanvas.Kisung
Seems to work but does this mean all of those bitmaps I've drawn previously remain on the canvas and are just covered up by a black layer? Is that bad for memory???Chirk
Crap, what's with translucent Canvas'?Inellineloquent
I believe this is subtly wrong. It clears the color channels of all of the pixels, but it doesn't clear their alpha channels because the default drawing behavior for Canvas seems to be some kind of blending. This can cause problems if you use the drawn on canvas's bitmap in another drawing operation later, and depend on blending there.Foramen
C
298

Draw transparent color with PorterDuff clear mode does the trick for what I wanted.

Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
Coastline answered 4/6, 2012 at 13:37 Comment(3)
This should work, but appears to be bugged in 4.4 (at least on the N7.2) Use Bitmap#eraseColor(Color.TRANSPARENT), as in HeMac's answer below.Foramen
In fact, Color.TRANSPARENT is unnecessary. PorterDuff.Mode.CLEAR is totally enough for a ARGB_8888 bitmap which means setting the alpha and color to [0, 0]. Another way is to use Color.TRANSPARENT with PorterDuff.Mode.SRC.Apnea
This is not working for me leaving a blank surface instead of TransparentVerdin
E
84

How do I clear (or redraw) the WHOLE canvas for a new layout (= try at the game) ?

Just call Canvas.drawColor(Color.BLACK), or whatever color you want to clear your Canvas with.

And: how can I update just a part of the screen ?

There is no such method that just update a "part of the screen" since Android OS is redrawing every pixel when updating the screen. But, when you're not clearing old drawings on your Canvas, the old drawings are still on the surface and that is probably one way to "update just a part" of the screen.

So, if you want to "update a part of the screen", just avoid calling Canvas.drawColor() method.

Euphemie answered 20/4, 2011 at 12:1 Comment(15)
No, if you do not draw every pixel in the surface you will get very strange results (because double buffering is achieved by swapping pointers, so in the parts where you are not drawing you will not see what was there just before). You have to redraw every pixel of the surface at each iteration.Naos
@Guillaume Brunerie: What you just described has absolutely nothing to do with what I wrote in my answer. The Canvas mechanism keeps old drawings if we're not clearing it with a different bitmap or color. That is theoreticlly correct and it is practically true.Euphemie
@Viktor Lannér: I tried your solution and the background is drawn anew. But all bitmaps called by "canvas. drawBitmap" from my array mBits[..] are STILL there. How can I get rid of these?Bandit
@Viktor Lannér: If you call mSurfaceHolder.unlockCanvasAndPost(c) and then c = mSurfaceHolder.lockCanvas(null), then the new c does not contain the same thing as the previous c. You can’t update just a part of a SurfaceView, which is what the OP was asking I guess.Naos
@samClem: That depends in which situation you're drawing your bitmaps. If you want to get rid of them, just clear the Canvas once more.Euphemie
@Guillaume Brunerie: True, but not all. You can't update a part of the screen, as I wrote. But you can keep old drawings on the screen, which will have the effect of just "update a part of the screen". Try it yourself in a sample application. Canvas keeps old drawings.Euphemie
SHAME ON ME !!! I did initialize my array only ONCE at game start NOT at the consecutive re-starts - so ALL OLD pieces remained "onscreen" - they were just drawn anew !!! I AM VERY SORRY for my "dumbness"! Thanks to both of you !!!Bandit
@Viktor Lannér: I just wrote a little activity which draw a new bitmap in the SurfaceView every second, and the behaviour is the one I’m describing. I can clearly see that there are two buffers, and that you are not always writing to the same buffer. I can post the code as a new answer if you want.Naos
@Guillaume Brunerie: Nope, it's fine since I have my own Live Wallpaper based on a Canvas, which is telling me the opposite behaviour. Of course you can post it for other visitors here, it is good to have multiple answers as we can inspect each others solutions.Euphemie
Then this is probably because Live wallpapers do not work the same way as a regular SurfaceView. Anyway, @samClem: always redraw every pixel of the Canvas at each frame (as stated in the doc) or you will have strange flickering.Naos
@Guillaume Brunerie: Well, that's not correct either. Live Wallpapers has the same SurfaceView as a regular application. Also, I have seen the same thing on one of my regular applications which have a SurfaceView. But as I said, post your answer so other can see what you're meaning.Euphemie
Let's not forget the possibility of the dirty rectangle that can be passed to lockCanvas.Kisung
Seems to work but does this mean all of those bitmaps I've drawn previously remain on the canvas and are just covered up by a black layer? Is that bad for memory???Chirk
Crap, what's with translucent Canvas'?Inellineloquent
I believe this is subtly wrong. It clears the color channels of all of the pixels, but it doesn't clear their alpha channels because the default drawing behavior for Canvas seems to be some kind of blending. This can cause problems if you use the drawn on canvas's bitmap in another drawing operation later, and depend on blending there.Foramen
C
37

Found this in google groups and this worked for me..

Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, clearPaint); 

This removes drawings rectangles etc. while keeping set bitmap..

Camper answered 4/9, 2012 at 12:13 Comment(3)
This gives me a black area - not the bitmap I have behind it :(Hawse
Its clears fine, but the bitmap is also remove unlike you said.Sweeper
in #9692485 is explained how to draw a rectangle of a bitmap on some rectangle of the canvas. Change an image in a rectangle thus works:lear the previous contents, draw the new imageKepi
M
24

use the reset method of Path class

Path.reset();
Mekka answered 6/11, 2013 at 12:22 Comment(3)
this really is the best answer if your using a path. the other ones can leave the user with a black screen. thanks.Sirreverence
super duper awesome. thanks. my situation was drawing a triangle with path by get touch events from user. so I wanted to clear previous drawn triangle while drawing new one to simulate moving of it. many thanks.Tithable
Sorry, I do not understand how to use this. If I draw the path on a canvas, this does not erase it. How to erase then?Calva
N
20

I tried the answer of @mobistry:

canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);

But it doesn't worked for me.

The solution, for me, was:

canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);

Maybe some one has the same problem.

Newish answered 21/5, 2014 at 4:47 Comment(1)
Multiplying with transparency is the answer. Otherwise it can end up black colored on some devices.Vorlage
F
13
mBitmap.eraseColor(Color.TRANSPARENT);

canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
Factorize answered 2/11, 2012 at 13:27 Comment(2)
how is this the most correct? why use a bitmap at all when you can just drawColor?Pam
Although this might not work for the original poster (they don't necessarily have access to the bitmap) this is definitely useful for clearing the contents of a bitmap when that's available. In those cases, only the first line is required. Useful technique, +1Blus
P
6
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
Poignant answered 5/3, 2017 at 7:38 Comment(1)
Please add an explanation of how your code solves the issue. This is flagged as low quality post - From ReviewConnection
C
4

please paste below code on surfaceview extend class constructor.............

constructor coding

    SurfaceHolder holder = getHolder();
    holder.addCallback(this);

    SurfaceView sur = (SurfaceView)findViewById(R.id.surfaceview);
    sur.setZOrderOnTop(true);    // necessary
    holder = sur.getHolder();
    holder.setFormat(PixelFormat.TRANSPARENT);

xml coding

    <com.welcome.panelview.PanelViewWelcomeScreen
        android:id="@+id/one"
        android:layout_width="600px"
        android:layout_height="312px"
        android:layout_gravity="center"
        android:layout_marginTop="10px"
        android:background="@drawable/welcome" />

try above code...

Covetous answered 22/6, 2012 at 7:25 Comment(1)
holder.setFormat(PixelFormat.TRANSPARENT); It works for me.Operator
N
3

Here is the code of a minimal example showing that you always have to redraw every pixel of the Canvas at each frame.

This activity draw a new Bitmap every second on the SurfaceView, without clearing the screen before. If you test it, you will see that the bitmap is not always written to the same buffer, and the screen will alternate between the two buffers.

I tested it on my phone (Nexus S, Android 2.3.3), and on the emulator (Android 2.2).

public class TestCanvas extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new TestView(this));
    }
}

class TestView extends SurfaceView implements SurfaceHolder.Callback {

    private TestThread mThread;
    private int mWidth;
    private int mHeight;
    private Bitmap mBitmap;
    private SurfaceHolder mSurfaceHolder;

    public TestView(Context context) {
        super(context);
        mThread = new TestThread();
        mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon);
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        mWidth = width;
        mHeight = height;
        mThread.start();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {/* Do nothing */}

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mThread != null && mThread.isAlive())
            mThread.interrupt();
    }

    class TestThread extends Thread {
        @Override
        public void run() {
            while (!isInterrupted()) {
                Canvas c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    synchronized (mSurfaceHolder) {
                        c.drawBitmap(mBitmap, (int) (Math.random() * mWidth), (int) (Math.random() * mHeight), null);
                    }
                } finally {
                    if (c != null)
                        mSurfaceHolder.unlockCanvasAndPost(c);
                }

                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    interrupt();
                }
            }
        }   
    }
}
Naos answered 20/4, 2011 at 13:26 Comment(6)
Well, it seems you're wrong, look at my screen capture here: img12.imageshack.us/i/devicey.png/# When you've added a delay like one second the double buffering is more noticed, but(!) there is still previous drawings on the screen. Also, your code is wrong: it should be SurfaceHolder.Callback, not just Callback.Euphemie
I think you don’t understand what I mean. What one could expect is that the difference between frame n and frame n+1 is that there is one more Bitmap. But this is completely wrong, there is one more Bitmap between frame n and frame n+2, but frame n and frame n+1 are completely unrelated even if I just added a Bitmap.Naos
Nope, I fully understand you. But, as you see, your code doesn't work. After a while, the screen is full with icons. Therefore, we need to clear the Canvas if we want to fully redraw the whole screen. That makes my statement about "previous drawings" true. The Canvas keeps previous drawings.Euphemie
Yes if you want, a Canvas keeps previous drawings. But this is completely useless, the problem is that when you use lockCanvas() you do not know what are those “previous drawing”, and cannot assume anything about them. Perhaps that if there are two activities with a SurfaceView of the same size, they will share the same Canvas. Perhaps that you get a chunk of uninitialized RAM with random bytes in it. Perhaps that there is always the Google logo written in the Canvas. You cannot know. Any application which is not drawing every pixel after lockCanvas(null) is broken.Naos
Well, I haven't said you know anything about the previous drawings, but they are still there. The Canvas don't know about the objects. What Canvas keeps are the previous drawings. This is true, according to me, according to your own application and it is a fact made by many other than me. I don't know what you're arguing about; you've already disproved your case.Euphemie
@GuillaumeBrunerie 2.5 yrs after the fact I've come across your post. Official Android documentation supports your advice concerning "drawing every pixel". There's only one case where a portion of the canvas is guaranteed to still be there with a subsequent call to lockCanvas(). Refer to the Android documentation for SurfaceHolder and its two lockCanvas() methods. developer.android.com/reference/android/view/… and developer.android.com/reference/android/view/…Bonheur
H
3

For me calling Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR) or something similar would only work after I touch the screen. SO I would call the above line of code but the screen would only clear after I then touched the screen. So what worked for me was to call invalidate() followed by init() which is called at the time of creation to initialize the view.

private void init() {
    setFocusable(true);
    setFocusableInTouchMode(true);
    setOnTouchListener(this);

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(Color.BLACK);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(6);

    mCanvas = new Canvas();
    mPaths = new LinkedList<>();

    addNewPath();
}
Hypertrophy answered 30/8, 2015 at 19:15 Comment(0)
C
2

Nov 2023
With the following approach, you can clear the whole canvas or just a part of it.
Please do not forget to disable Hardware acceleration since PorterDuff.Mode.CLEAR doesn’t work with hardware acceleration and finally call setWillNotDraw(false) because we override the onDraw method.

//view's constructor
setWillNotDraw(false);
setLayerType(LAYER_TYPE_SOFTWARE, null);


Paint transparentPaint = new Paint();
transparentPaint.setColor(Color.TRANSPARENT);
transparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

//view's onDraw
canvas.drawRect(0, 0, width, height, transparentPaint); 
Cimbura answered 22/8, 2019 at 13:8 Comment(6)
it's work, but after that my draws not visible morePenthouse
@DynoCris Perhaps you are using the same Paint object!? Try with a new one, and don't forget to upvote please.Cimbura
it's my code pastebin.com/GWBdtUP5 when i try to draw again i don't see lines more unfourtunatly. but cansvas is clear.Penthouse
@DynoCris Please change LAYER_TYPE_HARDWARE to LAYER_TYPE_SOFTWARECimbura
oh, really, it's my mistake. But it didn't help me anyway unfourtunatly.Penthouse
@DynoCris Not really... SorryCimbura
O
2

Erasing on Canvas in java android is similar erasing HTML Canvas via javascript with globalCompositeOperation. The logic was similar.

U will choose DST_OUT (Destination Out) logic.

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

Note: DST_OUT is more useful because it can erase 50% if the paint color have 50% alpha. So, to clear completely to transparent, the alpha of color must be 100%. Apply paint.setColor(Color.WHITE) is recommended. And make sure that the canvas image format was RGBA_8888.

After erased, go back to normal drawing with SRC_OVER (Source Over).

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

Update small area display literally will need to access graphic hardware, and it maybe not supported.

The most close for highest performance is using multi image layer.

Octosyllable answered 14/6, 2020 at 10:2 Comment(3)
Can you help me here? Yours is the only solution that has worked out for my case so i up voted, there is just a little problem that needs to be sort outCatamount
I am using canvas with surface holder, so i do this to clear canvas(canvas taken from surface holder): paint!!.setXfermode(PorterDuffXfermode(PorterDuff.Mode.DST_OUT)) canvas!!.drawPaint(paint!!) surfaceHolder!!.unlockCanvasAndPost(canvas) then to be able to redraw it: paint!!.setXfermode(PorterDuffXfermode(PorterDuff.Mode.SRC)) canvas!!.drawPaint(paint!!) surfaceHolder!!.unlockCanvasAndPost(canvas) now the problem is after clearing the canvas like this, when i draw a bitmap over canvas, it is drawn after a blink of Color, which is annoying, can u show me the way here? @OctosyllableCatamount
@hamza khan Have you tried with SRC_OVER? Because SRC_OVER is default normal. SRC logic is overwrite old pixel data, it replaces alpha!Octosyllable
C
2

I found my solution.

PaintView class:

public void clear() {
    mPath.reset();
    mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    paths.clear();
}

And MainActivity:

  clear_canvas_.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            paintView.clear();
        }
    });
Candace answered 11/1, 2022 at 7:19 Comment(0)
V
1

Don't forget to call invalidate();

canvas.drawColor(backgroundColor);
invalidate();
path.reset();
Verdict answered 17/8, 2019 at 16:28 Comment(1)
Why would you call invalidate after drawing something?Nakasuji
P
0

Your first requirement, how to clear or redraw whole canvas - Answer - use canvas.drawColor(color.Black) method for clearing the screen with a color of black or whatever you specify .

Your second requirement, how to update part of the screen - Answer - for example if you want to keep all other things unchanged on the screen but in a small area of screen to show an integer(say counter) which increases after every five seconds. then use canvas.drawrect method to draw that small area by specifying left top right bottom and paint. then compute your counter value(using postdalayed for 5 seconds etc., llike Handler.postDelayed(Runnable_Object, 5000);) , convert it to text string, compute the x and y coordinate in this small rect and use text view to display the changing counter value.

Paiz answered 8/4, 2013 at 1:28 Comment(0)
D
0

Try to remove the view at onPause() of an activity and add onRestart()

LayoutYouAddedYourView.addView(YourCustomView); LayoutYouAddedYourView.removeView(YourCustomView);

The moment you add your view, onDraw() method would get called.

YourCustomView, is a class which extends the View class.

Dogy answered 17/10, 2019 at 7:17 Comment(0)
U
0

In my case, I draw my canvas into linearlayout. To clean and redraw again:

    LinearLayout linearLayout = findViewById(R.id.myCanvas);
    linearLayout.removeAllViews();

and then, I call the class with the new values:

    Lienzo fondo = new Lienzo(this,items);
    linearLayout.addView(fondo);

This is the class Lienzo:

class Lienzo extends View {
    Paint paint;
    RectF contenedor;
    Path path;
    ArrayList<Items>elementos;

    public Lienzo(Context context,ArrayList<Items> elementos) {
        super(context);
        this.elementos=elementos;
        init();
    }

    private void init() {
        path=new Path();
        paint = new Paint();
        contenedor = new RectF();
        paint.setStyle(Paint.Style.FILL);
    }


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

        contenedor.left = oneValue;
        contenedor.top = anotherValue;
        contenedor.right = anotherValue;
        contenedor.bottom = anotherValue;

        float angulo = -90; //starts drawing at 12 o'clock
        //total= sum of all element values
        for (int i=0;i<elementos.size();i++){
            if (elementos.get(i).angulo!=0 && elementos.get(i).visible){
                paint.setColor(elementos.get(i).backColor);
                canvas.drawArc(contenedor,angulo,(float)(elementos.get(i).value*360)/total,true,paint);

                angulo+=(float)(elementos.get(i).value*360)/total;
            }
        } //for example
    }
}
Ulani answered 24/7, 2020 at 18:24 Comment(0)
D
0

In my case, creating canvas every time worked for me, even though it's not memory-friendly

Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.image);
imageBitmap = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
canvas = new Canvas(imageBitmap);
canvas.drawBitmap(bm, 0, 0, null);
Dinkins answered 15/2, 2021 at 15:43 Comment(0)
T
0

The following worked for me:

canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SCREEN);
Taillight answered 17/12, 2021 at 23:34 Comment(0)
C
-1

I had to use a separate drawing pass to clear the canvas (lock, draw and unlock):

Canvas canvas = null;
try {
    canvas = holder.lockCanvas();
    if (canvas == null) {
        // exit drawing thread
        break;
    }
    canvas.drawColor(colorToClearFromCanvas, PorterDuff.Mode.CLEAR);
} finally {
    if (canvas != null) {
        holder.unlockCanvasAndPost(canvas);
    }
}
Chivalry answered 12/8, 2018 at 18:51 Comment(0)
F
-3

Just call

canvas.drawColor(Color.TRANSPARENT)

Favored answered 29/11, 2011 at 9:20 Comment(1)
That doesn't work because it'll just draw transparency on top of the current clip...effectively doing nothing. You can, however, change the Porter-Duff transfer mode to achieve the desired effect: Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR). If I'm not mistaken, the color can actually be anything (doesn't have to be TRANSPARENT) because PorterDuff.Mode.CLEAR will just clear the current clip (like punching a hole in the canvas).Gospel

© 2022 - 2024 — McMap. All rights reserved.