Why is there an frame rectangle and an bounds rectangle in an UIView?
Here's the cheatsheet:
frame
is where the view is (with respect to the superview)bounds
is where the view is allowed to draw (with respect to itself)
Some more clarification:
If you are positioning the view in its superview, you almost always change the frame origin.
If you are clipping where the UIView is drawing, you almost always modify its bounds.
Note that you are allowed to have bounds that is bigger than the frame. That is, you can draw "outside the lines" of where you are.
Cocoa: What's the difference between the frame and the bounds?
The bounds of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to its own coordinate system (0,0).
The frame of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to the superview it is contained within.
So, imagine a view that has a size of 100x100 (width x height) positioned at 25,25 (x,y) of its superview. The following code prints out this view's bounds and frame:
// This method is in the view controller of the superview
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"bounds.origin.x: %f", label.bounds.origin.x);
NSLog(@"bounds.origin.y: %f", label.bounds.origin.y);
NSLog(@"bounds.size.width: %f", label.bounds.size.width);
NSLog(@"bounds.size.height: %f", label.bounds.size.height);
NSLog(@"frame.origin.x: %f", label.frame.origin.x);
NSLog(@"frame.origin.y: %f", label.frame.origin.y);
NSLog(@"frame.size.width: %f", label.frame.size.width);
NSLog(@"frame.size.height: %f", label.frame.size.height);
}
And the output of this code is:
bounds.origin.x: 0
bounds.origin.y: 0
bounds.size.width: 100
bounds.size.height: 100
frame.origin.x: 25
frame.origin.y: 25
frame.size.width: 100
frame.size.height: 100
So, we can see that in both cases, the width and the height of the view is the same regardless of whether we are looking at the bounds or frame. What is different is the x,y positioning of the view. In the case of the bounds, the x and y coordinates are at 0,0 as these coordinates are relative to the view itself. However, the frame x and y coordinates are relative to the position of the view within the parent view (which earlier we said was at 25,25).
There is also a great presentation that covers UIViews. See slides 1-20 which not only explain the difference between frames and bounds but also show visual examples.
Does it make sense that the bounds rectangle of an UIView can be bigger than the frame rectangle?
I just answered this in your other post:
Why is there an frame rectangle and an bounds rectangle in an UIView?
Basically, you are allowed to draw outside the frame if the bounds is set big enough. Imagine you are drawing a window. You need the frame to be the exact window dimensions for taps, clicks and UI purposes. However, you need to draw a shadow. If your bounds is bigger than the frame, you can draw the shadow (or any other outer border) outside of the frame.
UIView frame, bounds and center
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 frame
(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 bounds
(CGRect
) expresses a view rectangle in its own coordinate system.
Center A 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.
Using the 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 bounds
size
, 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 bounds
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 origin
for 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 view2
's frame
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;
The origin
represents the view
's position within its superview
but describes the position of the bounds
center.
Finally, bounds
and 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)
- UIView Geometry
- UIView Frames and Bounds
About 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
NO.
In other words, if a view's frame
is (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, clipsToBounds
calls masksToBounds
. For further references take a look to How is the relation between UIView's clipsToBounds and CALayer's masksToBounds?.
Bounds and Frame Size of a UIView
Try with Frame
instead of Bounds
CGRect frame = self.glView.frame;
frame.size.height = 927.0f;
frame.size.width = 619.0f;
frame.origin.x = 931.0f;
frame.origin.y = 65.0f;
self.glView.frame = frame;
The bounds of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to its own coordinate system (0,0).
The frame of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to the superview it is contained within.
So, frame will help you to adjust your view within superview.
Thanks
Do I have the right understanding of frames and bounds in UIKit?
Check out Apple's guide on View Geometry. They have pretty good examples on what happens when you change bounds and frame values.
why using two types (bounds/frame) to describe a view instead of one?
Taken from CocoaDev :
- The frame is expressed in the coordinate space of a view's superview.
- The bounds are expressed in a view's own coordinate space.
Visual explanation (by Apple Developer Reference) :
Reference : http://developer.apple.com/documentation/Cocoa/Conceptual/DrawViews/Concepts/ViewHierarchy.html
Custom UIView with smaller bounds than frame
A view's bounds represents the bounding rectangle in the view's own coordinate system. The frame is the bounding rectangle in the superview's coordinate system. By changing a view's transform, you could easily create a bounds rectangle with origin={0, 0} and size={1, 1}, even though the view's frame was origin={0, 0}, size={320, 480}. That view might cover the entire screen, but the bounds is still only 1 unit by 1 unit in size.
I see what you're trying to do, and that's really a different thing from bounds != frame. You're talking about having a content view that's only partially visible through an enclosing view. This is exactly what UIScrollView does for you.
Related Topics
Sending a Private Message to Your Friends via Facebook iOS Sdk
Aes/Cbc/Pkcs5Padding in iOS Objective C Result Differs from Android
Want to Create a Cool Static UI But:"Static Table Views Are Only Valid..."
How to Calculate Actual Font Point Size in iOS 7 (Not the Bounding Rectangle)
Can't Cast Value of Type Uiviewcontroller to Patterndetailviewcontroller
How to Save List of Object in User Default
Avcapturesession Audio Doesn't Work for Long Videos
Download and Cache Images in Uitableviewcell
Swift/How to Use Dispatch_Group with Multiple Called Web Service
Custom Class Clusters in Swift
Swiftui - Animations Triggered Inside a View That's in a List Doesn't Animate the List as Well
iOS - Swift - Function That Returns Asynchronously Retrieved Value
Swift - Error 'Expected ',' Separator' and 'Expected Expression in List of Expressions'
iOS Getting Location Updates When App Terminated Without Using Significantchange
How to Edit Uialertaction Text Font Size and Color