23
votes

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?

2
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
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
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 UIViewLefteris
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
(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

2 Answers

30
votes

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.

-3
votes

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