ios UIView 框架、边界和中心

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5361369/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:17:34  来源:igfitidea点击:

UIView frame, bounds and center

objective-ciosuiviewframebounds

提问by Lorenzo B

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

我想知道如何以正确的方式使用这些属性。

As I understand, framecan 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.

据我了解,frame可以从我正在创建的视图的容器中使用。它设置相对于容器视图的视图位置。它还设置该视图的大小。

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

center可以从我正在创建的视图的容器中使用。此属性更改视图相对于其容器的位置。

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

最后,bounds是相对于视图本身。它改变了视图的可绘制区域。

Can you give more info about the relationship between frameand bounds? What about the clipsToBoundsand masksToBoundsproperties?

你能给约之间的关系更多信息framebounds?怎么样clipsToBoundsmasksToBounds性质?

回答by Lorenzo B

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.

首先回顾一下这个问题:框架、边界和中心以及它们之间的关系。

FrameA view's frame(CGRect) is the position of its rectangle in the superview's coordinate system. By default it starts at the top left.

框架视图的frame( CGRect) 是其矩形在superview的坐标系中的位置。默认情况下,它从左上角开始。

BoundsA view's bounds(CGRect) expresses a view rectangle in its own coordinate system.

边界一个视图的bounds( CGRect) 在它自己的坐标系中表示一个视图矩形。

CenterA centeris a CGPointexpressed in terms of the superview's coordinate system and it determines the position of the exact center point of the view.

中心AcenterCGPoint根据superview的坐标系表示的,它确定视图的确切中心点的位置。

Taken from UIView + positionthese are the relationships (they don't work in code since they are informal equations) among the previous properties:

取自UIView + position这些是之前属性之间的关系(它们在代码中不起作用,因为它们是非正式方程):

  • frame.origin = center - (bounds.size / 2.0)

  • center = frame.origin + (bounds.size / 2.0)

  • frame.size = bounds.size

  • 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 Drawerbased on Stanford CS193pcourse. Credits goes to @Rhubarb.

注意:如果旋转视图,则这些关系不适用。有关更多信息,我建议您查看以下图片,图片取自基于斯坦福 CS193p课程的厨房抽屉。积分去@Rhubarb

Frame, bounds and center

框架、边界和中心

Using the frameallows 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:

使用frame允许您在其superview. 通常可以从 使用superview,例如,当您创建特定的子视图时。例如:

// 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 viewyou usually refer to bounds. A typical example could be to draw within a viewa subview as an inset of the first. Drawing the subview requires to know the boundsof the superview. For example:

当您需要在 a 内绘制坐标时,view您通常会参考bounds. 一个典型的例子可能是在view一个子视图中绘制作为第一个的插图。绘制子视图需要知道bounds父视图的。例如:

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 boundsof a view. For example, if you change the boundssize, the framechanges (and vice versa). The change happens around the centerof the view. Use the code below and see what happens:

更改bounds视图的时会发生不同的行为。例如,如果你改变了boundssize,对frame改变(反之亦然)。变化发生在center视图的周围。使用下面的代码,看看会发生什么:

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 boundsoriginyou change the originof its internal coordinate system. By default the originis at (0.0, 0.0)(top left corner). For example, if you change the originfor view1you can see (comment the previous code if you want) that now the top left corner for view2touches the view1one. The motivation is quite simple. You say to view1that its top left corner now is at the position (20.0, 20.0)but since view2's frameoriginstarts from (20.0, 20.0), they will coincide.

此外,如果您更改,boundsorigin则会更改origin其内部坐标系的 。默认情况下origin位于(0.0, 0.0)(左上角)。例如,如果您更改originforview1您可以看到(如果您愿意,可以评论前面的代码)现在左上角的 forview2触及了那个view1。动机很简单。您说它的view1左上角现在位于 位置,(20.0, 20.0)但由于view2'sframeorigin从 开始(20.0, 20.0),它们将重合。

CGRect frame = view1.bounds;
frame.origin.x += 20.0f;
frame.origin.y += 20.0f;
view1.bounds = frame; 

The originrepresents the view's position within its superviewbut describes the position of the boundscenter.

origin代表view的地位及其内superview,但描述的位置bounds中心。

Finally, boundsand originare not related concepts. Both allow to derive the frameof a view (See previous equations).

最后,boundsorigin不是相关的概念。两者都允许导出frame视图的 的(参见前面的等式)。

View1's case study

View1 的案例研究

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.

如果我[self view]像下面这样更改边界,则会发生这种情况。

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

在这里,您说它的[self view]左上角现在位于 (30.0, 20.0) 位置,但由于view1的帧原点从 (30.0, 20.0) 开始,因此它们将重合。

Additional references(to update with other references if you want)

其他参考资料(如果需要,可以更新其他参考资料)

About clipsToBounds(source Apple doc)

关于clipsToBounds(来源 Apple 文档)

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.

将此值设置为 YES 会导致子视图被裁剪到接收器的边界。如果设置为 NO,则不会剪裁帧超出接收器可见边界的子视图。默认值为否。

In other words, if a view's frameis (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.

换句话说,如果一个视图的frameis(0, 0, 100, 100)和它的子视图是(90, 90, 30, 30),您将只能看到该子视图的一部分。后者将不超过父视图的边界。

masksToBoundsis equivalent to clipsToBounds. Instead to a UIView, this property is applied to a CALayer. Under the hood, clipsToBoundscalls masksToBounds. For further references take a look to How is the relation between UIView's clipsToBounds and CALayer's masksToBounds?.

masksToBounds相当于clipsToBounds。而不是 a UIView,此属性应用于 a CALayer。在幕后,clipsToBounds调用masksToBounds. 如需进一步参考,请查看UIView 的 clipsToBounds 和 CALayer 的 maskToBounds 之间的关系如何?.

回答by Suragch

This question already has a good answer, but I want to supplement it with some more pictures. My full answer is here.

这个问题已经有了很好的答案,但我想再补充一些图片。我的完整答案在这里。

To help me remember frame, I think of a picture frame on a wall. Just like a picture can be moved anywhere on the wall, the coordinate system of a view's frame is the superview. (wall=superview, frame=view)

为了帮助我记住相框,我想到了墙上的相框。就像一张图片可以移动到墙上的任何地方一样,视图框架的坐标系是超级视图。(墙=超级视图,框架=视图)

To help me remember bounds, I think of the bounds of a basketball court. The basketball is somewhere within the court just like the coordinate system of the view's bounds is within the view itself. (court=view, basketball/players=content inside the view)

为了帮助我记住边界,我想到了篮球场的边界。篮球在球场内的某个地方,就像视图边界的坐标系在视图本身内一样。(球场=视图,篮球/球员=视图内的内容)

Like the frame, view.centeris also in the coordinates of the superview.

和frame一样,view.center也在superview的坐标中。

Frame vs Bounds - Example 1

帧与边界 - 示例 1

The yellow rectangle represents the view's frame. The green rectangle represents the view's bounds. The red dot in both images represents the origin of the frame or bounds within their coordinate systems.

黄色矩形代表视图的框架。绿色矩形代表视图的边界。两个图像中的红点表示框架的原点或坐标系内的边界。

Frame
    origin = (0, 0)
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

enter image description here

在此处输入图片说明



Example 2

示例 2

Frame
    origin = (40, 60)  // That is, x=40 and y=60
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

enter image description here

在此处输入图片说明



Example 3

示例 3

Frame
    origin = (20, 52)  // These are just rough estimates.
    width = 118
    height = 187

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

enter image description here

在此处输入图片说明



Example 4

示例 4

This is the same as example 2, except this time the whole content of the view is shown as it would look like if it weren't clipped to the bounds of the view.

这与示例 2 相同,不同之处在于这次视图的整个内容显示为没有裁剪到视图边界时的样子。

Frame
    origin = (40, 60)
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

enter image description here

在此处输入图片说明



Example 5

例 5

Frame
    origin = (40, 60)
    width = 80
    height = 130

Bounds 
    origin = (280, 70)
    width = 80
    height = 130

enter image description here

在此处输入图片说明

Again, see herefor my answer with more details.

再次,请参阅此处了解更多详细信息的答案。

回答by Erben Mo

I found this image most helpful for understanding frame, bounds, etc.

我发现这张图片对理解框架、边界等最有帮助。

enter image description here

在此处输入图片说明

Also please note that frame.size != bounds.sizewhen the image is rotated.

另请注意,frame.size != bounds.size当图像旋转时。

回答by coolbeet

I think if you think it from the point of CALayer, everything is more clear.

我想如果你从这个角度来思考CALayer,一切就更清楚了。

Frame is not really a distinct property of the view or layer at all, it is a virtual property, computed from the bounds, position(UIView's center), and transform.

Frame 根本不是视图或图层的独特属性,它是一个虚拟属性,根据边界、位置(UIView的中心)和变换计算。

So basically how the layer/view layouts is really decided by these three property(and anchorPoint), and either of these three property won't change any other property, like changing transform doesn't change bounds.

所以基本上层/视图布局是如何由这三个属性(和锚点)真正决定的,这三个属性中的任何一个都不会改变任何其他属性,就像改变变换不会改变边界一样。

回答by Wael Showair

There are very good answers with detailed explanation to this post. I just would like to refer that there is another explanation with visual representation for the meaning of Frame, Bounds, Center, Transform, Bounds Origin in WWDC 2011 video Understanding UIKit Renderingstarting from @4:22 till 20:10

这篇文章有很好的答案和详细的解释。我只是想参考在WWDC 2011视频Understanding UIKit Rendering startsfrom @4:22 to 20:10 Frame, Bounds, Center, Transform, Bounds Origin 的含义还有另一种可视化的解释

回答by NSTNF

After reading the above answers, here adding my interpretations.

阅读以上答案后,在这里添加我的解释。

Suppose browsing online, web browseris your framewhich decides where and how big to show webpage. Scrollerof browser is your bounds.originthat decides which part of webpage will be shown. bounds.originis hard to understand. The best way to learn is creating Single View Application, trying modify these parameters and see how subviews change.

假设在线浏览,网络浏览器是您frame决定显示网页的位置和大小。浏览器的滚动条是您bounds.origin决定网页的哪一部分显示的。bounds.origin很难理解。最好的学习方法是创建单一视图应用程序,尝试修改这些参数并查看子视图如何变化。

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(100.0f, 200.0f, 200.0f, 400.0f)];
[view1 setBackgroundColor:[UIColor redColor]];

UIView *view2 = [[UIView alloc] initWithFrame:CGRectInset(view1.bounds, 20.0f, 20.0f)];
[view2 setBackgroundColor:[UIColor yellowColor]];
[view1 addSubview:view2];

[[self view] addSubview:view1];

NSLog(@"Old view1 frame %@, bounds %@, center %@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds), NSStringFromCGPoint(view1.center));
NSLog(@"Old view2 frame %@, bounds %@, center %@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds), NSStringFromCGPoint(view2.center));

// Modify this part.
CGRect bounds = view1.bounds;
bounds.origin.x += 10.0f;
bounds.origin.y += 10.0f;

// incase you need width, height
//bounds.size.height += 20.0f;
//bounds.size.width += 20.0f;

view1.bounds = bounds;

NSLog(@"New view1 frame %@, bounds %@, center %@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds), NSStringFromCGPoint(view1.center));
NSLog(@"New view2 frame %@, bounds %@, center %@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds), NSStringFromCGPoint(view2.center));