23

I thought from some point on for OS X, and always true for iOS, that content can appear outside of the view's bounds? (for UIView) But if I create a brand new Single View app, and created a MyView class that subclasses UIView, and implement its drawRect:

- (void)drawRect:(CGRect)rect
{
    // Drawing code
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:
                                           CGRectMake(-20, -20, 600, 600)];
    [[UIColor greenColor] set];
    [path fill];

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [[UIColor blueColor] CGColor]);
    CGContextFillRect(context, CGRectMake(-20, -20, 600, 600));
}

I use both UI and CG to draw a rectangle each, just in case one works and the other doesn't. And the view is added in viewDidAppear:

- (void)viewDidAppear:(BOOL)animated {
    MyView *myView = [[MyView alloc] initWithFrame:CGRectMake(20, 20, 260, 260)];
    [self.view addSubview:myView];
}

But no matter what, the colored box won't go beyond the (20, 20, 260, 260) region. Is it true that only the CALayers can be freely added and appear outside of a view's bounds? Can it be because of the graphics context is limited to this (20, 20, 260, 260) to begin with? If so, is there a way to make drawRect content appear outside of the view's bound, in all four top, down, left, right directions?

nonopolarity
  • 146,324
  • 131
  • 460
  • 740
  • Can I ask, why do you want to draw outside the visible rect, since it won't be visible? If you plan on making it visible later, you should use a CALayer as you correctly mentioned. – Lefteris Sep 23 '12 at 09:03
  • one reason is, I am thinking of implementing a PopoutScrollView that has round corners, or even "cloud like edges". I found that I can subclass UIView and have a UIScrollView as a property, so that the scrollview is a subview of the view, and I actually have to override `addSubview` to add to `self.scrollView`. This is because I can't simply draw the borders on a scrollView, or else they will scroll away. This can be complicated, and I thought, why not just subclass UIScrollView, and in drawRect, draw outside the bounds? Then I don't have to override so many methods. – nonopolarity Sep 23 '12 at 09:10
  • Although I haven't tried this, but I don't see a reason for this not working, adding rounded corners to the scrollview, through the scrollview.layer.cornerRadius property should do this easy for you. Also if you plan to modify a scrollView, you should subclass the scrollview and it's drawRect method, rather than a UIView – Lefteris Sep 23 '12 at 09:14
  • so you mean not using drawRect to draw the layer with the round corners? Isn't it true that if I subclass UIScrollView and draw round corners using drawRect, then the border will "scroll away" just like any other content? Or unless `[aScrollView addSubview: v]` is actually adding to another UIView object which is a property of UIScrollView, so UIScrollView's drawRect actually is not drawing into that subview and so there is no problem? – nonopolarity Sep 23 '12 at 09:25
  • (what I mean is, not using drawRect to draw the layer, but probably in `initWithFrame`, create a bitmap context, draw a good "background border image", get the cgImage, and add as a sublayer to the view's layer? By the way I tried subclassing UIScrollView and use drawRect to draw the borders and they won't be scrolled away) – nonopolarity Sep 23 '12 at 09:37
  • Why should the be scrolled away? You are not drawing them in the contentView of the scrollView, but the scrollView it self. – Lefteris Sep 23 '12 at 09:41
  • and is it true that when `[aScrollView addSubview: v]`, then v is actually added to the contentView? I didn't know what goes underneath the UIScrollView interface – nonopolarity Sep 23 '12 at 10:56
  • Correct. It's a subview and you can then set the scrollView's content size via the setContentSize method. – Lefteris Sep 23 '12 at 11:27
  • I'm having a similar problem trying to draw a path around a UIView by overriding drawRect and drawing a path (for highlighting a UIImage by drawing a colored border around it). But my path is clipping to the inside of the image. Surely we can modify the clipping path instead of having to add another, larger layer image over the UIView I want to highlight. I've tried variations of masksToBounds and clipsToBounds with no positive results. – cod3monk3y Feb 06 '13 at 03:23

2 Answers2

31

Your problem is that "drawRect" is automatically clipped to the view that you are drawing in.

Instead of doing the drawing in the view itself, add a second (sub)view to the first view, that is outside the bounds of the first view. This will allow you to do drawing that is dependent on the placement of the first view, but is outside the first view's bounds.

Hope this helps.

Tim Kokesh
  • 879
  • 7
  • 10
-3

Try this on a view, where you have added the scrollView:

self.scrollView.backgroundColor = [UIColor darkGrayColor];
self.scrollView.layer.cornerRadius = 10.0f;
self.scrollView.layer.masksToBounds = YES;

It should display a gray scrollview with rounded corners, as you want.

Remember you need to import the QuartzCore FrameWork

Lefteris
  • 14,550
  • 2
  • 56
  • 95
  • what if it needs to go out of the bounds? – nonopolarity Sep 23 '12 at 11:00
  • I don't understand the question – Lefteris Sep 23 '12 at 11:28
  • I mean, the code above will draw the background all within the view's bounds. What if we need to draw something 10 pixels above the top, 10 pixels to the left of the left margin, etc. (draw something, or in this case is to draw the background and round corners) – nonopolarity Sep 23 '12 at 21:35