Using clipRect - explanation
Asked Answered
S

4

48
public class POCII extends Activity { 

    myView mv = new myView(this); 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(mv); 
    }
}


class myView extends View { 

    public myView(Context context) { 
       super(context); 
    } 

    @Override 
    public void onDraw(Canvas canvas) { 

        Paint paint = new Paint(); 

        canvas.drawRect(0,0,100,100, paint); 
        canvas.clipRect(0,0,50,50);
    } 
}

My question is, shouldn't the above code draw a rectangle and then crop the top left portion? The rectangle is not getting cropped.

Please explain what clipRect does. What is it actually clipping? Does it clip in the form of a rectangle, given the co-ordinates? If so, Why is the above code not working?

Suwannee answered 26/7, 2010 at 1:54 Comment(1)
check youtu.be/vkTn3Ule4Ps?list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiuInclination
E
85

Canvas.clipRect(left, top, right, bottom) reduces the region of the screen that future draw operations can write to. It sets the clipBounds to be the spacial intersection of the current clipping rectangle and the rectangle specified. There are lot of variants of the clipRect method that accept different forms for regions and allow different operations on the clipping rectangle. If you want to explicitly set the clipping region, try:

canvas.clipRect(left, top, right, bottom, Region.Op.REPLACE);

The 5th argument means replace the clipping rectangle rather than creating the intersection with the previous version.

Try moving the clipRect statement before the drawRect statement. Or, try adding:

paint.setColor(Color.YELLOW);
drawRect(0,0,75,75);

after your existing clipRect statement. It should draw a 50x50 yellow square over what you had before.

Another note: (after long frustration with the apparently, largely undocumented View/ViewGroup/drawing code) I found that canvas.translate(x,y) also adjusts the clipRect. The interaction of clipRect and the drawing matrix is very confusing. It is helpful to point out:

canvas.getMatrix()

and

canvas.getClipBounds()

before and after modifications to the canvas and before drawing things.

Etheleneethelin answered 10/1, 2011 at 21:25 Comment(9)
The note on canvas.translate(x,y) messing with the clipRect was very useful. Saved me a lot of frustration. Thanks!Outthink
The methods with Region.Op are apparently deprecated now.Something
How to get the original canvas from the clipped canvas?Hastings
@Something That's true (though technically they are not methods) , but what should be used instead?Michael
@androiddeveloper, the documentation for the clipRect method recommends some alternatives. Why do you say clipRect (and clipPath) with Region.Op aren't technically methods?Something
@Something OK I will see what I can do. Forget the part of the methods. I thought you meant something else (that Region.Op values are methods), but you meant the methods of canvas that use Region.Op.Michael
@Something I tried to use clipOutRect instead of clipRect with Region.Op.REPLACE. Didn't work. Should I use something else instead? If so, what's the equivalent?Michael
@androiddeveloper, I'm afraid you're going beyond what I know. Sorry. This sounds worthy of a new question.Something
@androiddeveloper The clipOutXXX method only work on API level 26 above, check the docs: developer.android.com/reference/android/graphics/…Snowfield
M
5

To crop the top left portion, do:

canvas.clipRect(0,0,50,50, Region.Op.DIFFERENCE);
// secondly...
canvas.drawRect(0,0,100,100, paint); 
Mountford answered 6/9, 2012 at 18:55 Comment(0)
M
4

ICS and above ...

XOR, Difference and ReverseDifference clip modes are ignored by ICS if hardware acceleration is enabled.

Just disable 2D hardware acceleration in your view:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Reference Android: Howto use clipRect in API15

Missilery answered 24/1, 2014 at 7:29 Comment(0)
Y
3

your drawing looks like this without using cliprect:

enter image description here

now if we use a cliprect we are putting a overlay of a rectange over what we already have. its sort of invisible. lets say we called the following:

 override fun onDraw(canvas: Canvas) {

        val paint =  Paint();
        paint.color = Color.RED
        canvas.clipRect(0f,0f,500f,500f, Region.Op.DIFFERENCE);
// secondly...
        canvas.drawRect(0f,0f,1000f,1000f, paint);
    }

since we use DIFFERENCE option and we know the clipping rectangle is now OVER our canvas red rectangle we can tell me special things. above says we should KEEP the DIFFERENCE between the clipping rectangle and the original. so it will look like this (since i used half of 1000 for clipping rectangle):

enter image description here

and the opposite if we used intersect would look like this: enter image description here

i'd love to see if someone can make it do rounded corners.

Yttria answered 2/1, 2020 at 15:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.