Search code examples
ioscocoa-touchuiviewboundscgrect

Changing a view's bounds doesn't change where it draws


In viewDidLoad, I create a UIView at 100,100 with a size of 200x200, then change it's bounds to have an origin of -100,-100. I had supposed that this would either move the entire view back to the top left, or only draw a smaller rectangle for the intersection of the frame and bounds. It didn't affect the drawn-into area at all.

- (void)viewDidLoad
{
    [super viewDidLoad];

    CGRect rect = CGRectMake(100, 100, 200, 200);
    greenView = [[UIView alloc] initWithFrame:rect];
    [greenView setBackgroundColor:[UIColor greenColor]];

    CGRect bounds = CGRectMake(-100, -100, 200, 200);
    [greenView setBounds:bounds];
    [greenView setClipsToBounds:YES];
    [greenView setContentMode:UIViewContentModeRedraw];

    [self.view addSubview:greenView];
}

The frame and bounds log as follows:

Frame: {{100, 100}, {200, 200}}
Bounds: {{-100, -100}, {200, 200}}

I thought that a view only draws into it's bounds rect. What am I missing about views and bounds? Why doesn't changing my view's bounds change where it draws?

Here's what it looks like:

enter image description here


Solution

  • As suggested by Maddy, for your use case you just change the frame. Here is what happens behind the scenes:

    Changing the frame is like changing bounds and center of the view. So if you want to use bounds, also change the center. Please note that the size of the frame is not necessarily the same as the size of thebounds` because the view might be rotated.

    Therefore, your statement "I thought that a view only draws into it's bounds rect." is if not incorrect at least not precise enough. If you rotate your {200,200} view by 45 degrees, its bounds would still be {200,200}, but its frame.size will be 200 * sqrt(2) for both width and height. The bounds refer to the view's own coordinate system, the frame to that of the superview.