38

I'm porting an app written in a graphics environment that allows drawing to happen outside the bounds of the clipping rectangle. Any way to do this in Android?

Mark
  • 1,049
  • 4
  • 12
  • 14

6 Answers6

54

try to set

android:clipChildren="false" 

to the parent view

Danylo.Vus
  • 969
  • 9
  • 11
48

To draw outside the bounds, you need to expand the clipRect of the canvas.

Check out the overloaded clipRect methods on the Canvas class.

Note - You will need to specify the Region operation because the default operation is INTERSECT. So something like this:

Rect newRect = canvas.getClipBounds();
newRect.inset(-5, -5)  //make the rect larger

canvas.clipRect (newRect, Region.Op.REPLACE);
//happily draw outside the bound now
uthark
  • 5,333
  • 2
  • 43
  • 59
numan salati
  • 19,394
  • 9
  • 63
  • 66
  • 2
    It doesn't work at all. I just resize canvas with (-2000, -2000) parameters, then translate it but the image I draw is still clipped. – tomrozb Sep 27 '13 at 07:58
  • but if you do that on every `onDraw(Canvas canvas)` then aren't you making the computer do a lot of extra work ? – Someone Somewhere Jan 06 '14 at 04:42
  • @SomeoneSomewhere i am not sure what the effect on performance is when you change clip rects (esp. with HA on vs software rendering). but this should be simple to measure through profiling. – numan salati Jan 07 '14 at 18:19
  • This works the first time Invalidate is called. Subsequent calls do not work. – jjxtra Sep 01 '15 at 19:38
  • 6
    Region.Op.REPLACE got deprecated at API >= 26 Do you have another solution? Im running out all SOF and didnt found yet – Arthur Melo Feb 28 '19 at 22:01
10

You can draw where you like, but nothing will be saved outside the clipping rectangle.

CaseyB
  • 24,780
  • 14
  • 77
  • 112
3

The answer @numan gave is almost ok, the problem is memory allocation with that approach, so we should be doing this, instead:

// in constructor/elsewhere
Rect newRect = new Rect();

// in onDraw
canvas.getClipBounds(newRect);
newRect.inset(0, -20);  //make the rect larger
canvas.clipRect(newRect, Region.Op.REPLACE);

That solves the problem :-)

Tom
  • 6,946
  • 2
  • 47
  • 63
cesards
  • 15,882
  • 11
  • 70
  • 65
3

If you want to draw text out of bounds in TextView, you should be doing this instead:

<TextView
    ...
    android:shadowColor="#01000000"
    android:shadowDx="100" // out of right bound
    android:shadowDy="0"
    android:shadowRadius="1"
.../>

It's not working to use clipRect() like @numan's answer because TextView clip it's own rect in onDraw():

if (mShadowRadius != 0) {
    clipLeft += Math.min(0, mShadowDx - mShadowRadius);
    clipRight += Math.max(0, mShadowDx + mShadowRadius);

    clipTop += Math.min(0, mShadowDy - mShadowRadius);
    clipBottom += Math.max(0, mShadowDy + mShadowRadius);
}

canvas.clipRect(clipLeft, clipTop, clipRight, clipBottom);

Last but not least, Don't forget to set android:clipChildren="false" and android:clipToPadding="false" in your parent ViewGroup

legendmohe
  • 750
  • 7
  • 11
  • [SOLVED] WOKED! ((ViewGroup) parent).setClipChildren(true); ((ViewGroup) parent).setClipToPadding(true); solved for my using this when I needed to draw over the other views at same hierarchy thx ! – Arthur Melo Feb 28 '19 at 22:07
2

If what you want is just draw outside the view bounds (programmatically), cut the long story short.

parentLayout.setClipChildren(false);

or via xml :

 android:clipChildren="false"

enter image description here

ucMedia
  • 4,105
  • 4
  • 38
  • 46