Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView frame, bounds and center

I would like to know how to use these properties in the right manner.

As I understand, frame can be used from the container of the view I am creating. It sets the view position relative to the container view. It also sets the size of that view.

Also center can be used from the container of the view I'm creating. This property changes the position of the view relative to its container.

Finally, bounds is relative to the view itself. It changes the drawable area for the view.

Can you give more info about the relationship between frame and bounds? What about the clipsToBounds and masksToBounds properties?

like image 545
Lorenzo B Avatar asked Mar 19 '11 09:03

Lorenzo B


People also ask

What is the difference between frame and bounds in UIView?

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.

What is frame and bounds in IOS?

Short description. frame = a view's location and size using the parent view's coordinate system ( important for placing the view in the parent) bounds = a view's location and size using its own coordinate system (important for placing the view's content or subviews within itself)

What is bounds in Swift?

The bounds of a view describes the views location and size in its own coordinate system. This is what the Apple documentation says: The bounds rectangle, which describes the view's location and size in its own coordinate system. Even when rotate the x , y , width and height will stay the same.

What is frame in Xcode?

The frame rectangle, which describes the view's location and size in its superview's coordinate system.


1 Answers

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.

Frame, bounds and center

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.

enter image description here

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.

enter image description here

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?.

like image 197
14 revs, 3 users 91% Avatar answered Oct 02 '22 23:10

14 revs, 3 users 91%