Since the question I asked has been seen many times I will provide a detailed answer of it. Feel free to modify it if you want to add more correct content.
First a recap on the question: frame, bounds and center and theirs relationships.
Frame A view’s
CGRect) is the position of its rectangle in the
superview‘s coordinate system. By default it starts at the top left.
Bounds A view’s
CGRect) expresses a view rectangle in its own coordinate system.
center is a
CGPoint expressed in terms of the
superview‘s coordinate system and it determines the position of the exact center point of the view.
Taken from UIView + position these are the relationships (they don’t work in code since they are informal equations) among the previous properties:
frame.origin = center - (bounds.size / 2.0)
center = frame.origin + (bounds.size / 2.0)
frame.size = bounds.size
NOTE: These relationships do not apply if views are rotated. For further info, I will suggest you take a look at the following image taken from The Kitchen Drawer based on Stanford CS193p course. Credits goes to @Rhubarb.
frame allows you to reposition and/or resize a view within its
superview. Usually can be used from a
superview, for example, when you create a specific subview. For example:
// view1 will be positioned at x = 30, y = 20 starting the top left corner of [self view] // [self view] could be the view managed by a UIViewController UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 20.0f, 400.0f, 400.0f)]; view1.backgroundColor = [UIColor redColor]; [[self view] addSubview:view1];
When you need the coordinates to drawing inside a
view you usually refer to
bounds. A typical example could be to draw within a
view a subview as an inset of the first. Drawing the subview requires to know the
bounds of the superview. For example:
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(50.0f, 50.0f, 400.0f, 400.0f)]; view1.backgroundColor = [UIColor redColor]; UIView* view2 = [[UIView alloc] initWithFrame:CGRectInset(view1.bounds, 20.0f, 20.0f)]; view2.backgroundColor = [UIColor yellowColor]; [view1 addSubview:view2];
Different behaviours happen when you change the
bounds of a view.
For example, if you change the
frame changes (and vice versa). The change happens around the
center of the view. Use the code below and see what happens:
NSLog(@"Old Frame %@", NSStringFromCGRect(view2.frame)); NSLog(@"Old Center %@", NSStringFromCGPoint(view2.center)); CGRect frame = view2.bounds; frame.size.height += 20.0f; frame.size.width += 20.0f; view2.bounds = frame; NSLog(@"New Frame %@", NSStringFromCGRect(view2.frame)); NSLog(@"New Center %@", NSStringFromCGPoint(view2.center));
Furthermore, if you change
origin you change the
origin of its internal coordinate system. By default the
origin is at
(0.0, 0.0) (top left corner). For example, if you change the
view1 you can see (comment the previous code if you want) that now the top left corner for
view2 touches the
view1 one. The motivation is quite simple. You say to
view1 that its top left corner now is at the position
(20.0, 20.0) but since
origin starts from
(20.0, 20.0), they will coincide.
CGRect frame = view1.bounds; frame.origin.x += 20.0f; frame.origin.y += 20.0f; view1.bounds = frame;
origin represents the
view‘s position within its
superview but describes the position of the
origin are not related concepts. Both allow to derive the
frame of a view (See previous equations).
View1’s case study
Here is what happens when using the following snippet.
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 20.0f, 400.0f, 400.0f)]; view1.backgroundColor = [UIColor redColor]; [[self view] addSubview:view1]; NSLog(@"view1's frame is: %@", NSStringFromCGRect([view1 frame])); NSLog(@"view1's bounds is: %@", NSStringFromCGRect([view1 bounds])); NSLog(@"view1's center is: %@", NSStringFromCGPoint([view1 center]));
The relative image.
This instead what happens if I change
[self view] bounds like the following.
// previous code here... CGRect rect = [[self view] bounds]; rect.origin.x += 30.0f; rect.origin.y += 20.0f; [[self view] setBounds:rect];
The relative image.
Here you say to
[self view] that its top left corner now is at the position (30.0, 20.0) but since
view1‘s frame origin starts from (30.0, 20.0), they will coincide.
Additional references (to update with other references if you want)
clipsToBounds (source Apple doc)
Setting this value to YES causes subviews to be clipped to the bounds
of the receiver. If set to NO, subviews whose frames extend beyond the
visible bounds of the receiver are not clipped. The default value is
In other words, if a view’s
(0, 0, 100, 100) and its subview is
(90, 90, 30, 30), you will see only a part of that subview. The latter won’t exceed the bounds of the parent view.
masksToBounds is equivalent to
clipsToBounds. Instead to a
UIView, this property is applied to a
CALayer. Under the hood,
masksToBounds. For further references take a look to How is the relation between UIView’s clipsToBounds and CALayer’s masksToBounds?.