我想知道如何以正确的方式使用这些属性。
据我所知,frame可以从我正在创建的视图的容器中使用。 它设置了相对于容器视图的视图位置。它还设置了视图的大小。
也可以从我正在创建的视图容器中使用center。此属性更改视图相对于其容器的位置。
最后,bounds是相对于视图本身的。它改变了视图的可绘制区域。
你能提供更多关于框架和边界关系的信息吗?clipsToBounds和masksToBounds属性如何?
我想知道如何以正确的方式使用这些属性。
据我所知,frame可以从我正在创建的视图的容器中使用。 它设置了相对于容器视图的视图位置。它还设置了视图的大小。
也可以从我正在创建的视图容器中使用center。此属性更改视图相对于其容器的位置。
最后,bounds是相对于视图本身的。它改变了视图的可绘制区域。
你能提供更多关于框架和边界关系的信息吗?clipsToBounds和masksToBounds属性如何?
当前回答
我认为如果你从CALayer的角度来思考,一切都更清楚了。
Frame并不是视图或层的独立属性,它是一个虚拟属性,由边界、位置(UIView的中心)和变换计算而来。
所以基本上图层/视图布局是由这三个属性(和anchorPoint)决定的,这三个属性中的任何一个都不会改变任何其他属性,比如改变transform不会改变边界。
其他回答
我发现这张图对理解框架、边界等很有帮助。
也请注意这个框架。Size != bounds。图像旋转时的大小。
因为我问的问题已经被看到很多次了,所以我将提供一个详细的答案。如果您想添加更多正确的内容,请随意修改。
首先回顾一下这个问题:框架、边界和中心以及它们之间的关系。
视图的框架(CGRect)是它的矩形在父视图坐标系中的位置。默认情况下,它从左上角开始。
一个视图的边界(CGRect)在它自己的坐标系统中表示一个视图矩形。
中心中心是一个用父视图坐标系表示的CGPoint,它确定了视图的确切中心点的位置。
从UIView + position来看,这些是前面属性之间的关系(它们在代码中不起作用,因为它们是非正式的方程):
框架。原点=中心-(边界。尺寸/ 2.0) 中心=框架。原点+(边界。尺寸/ 2.0) 框架。Size = bounds.size
注意:如果视图被旋转,则这些关系不适用。想了解更多信息,我建议你看看下面这张取自斯坦福CS193p课程《厨房抽屉》的图片。感谢@大黄。
使用框架允许您在其父视图中重新定位和/或调整视图的大小。通常可以从父视图中使用,例如,当您创建特定的子视图时。例如:
// 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];
当你需要在视图中绘制坐标时,你通常会引用边界。一个典型的例子是在视图中绘制子视图作为第一个视图的嵌入。绘制子视图需要知道父视图的边界。例如:
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];
当您更改视图的边界时,会发生不同的行为。 例如,如果你改变了边界大小,帧也会改变(反之亦然)。变化发生在视图的中心周围。使用下面的代码,看看会发生什么:
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;
原点表示视图在父视图中的位置,但描述边界中心的位置。
最后,边界和原点不是相关的概念。两者都可以推导出视图的框架(参见前面的方程)。
View1的案例研究
下面是使用以下代码段时会发生的情况。
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]));
相对像。
相反,如果我像下面这样改变[自我视图]边界,就会发生这种情况。
// previous code here...
CGRect rect = [[self view] bounds];
rect.origin.x += 30.0f;
rect.origin.y += 20.0f;
[[self view] setBounds:rect];
相对像。
这里你告诉[self view]它的左上角现在位于(30.0,20.0)位置,但由于view1的帧原点从(30.0,20.0)开始,它们将重合。
其他引用(如果需要,可以使用其他引用进行更新)
UIView几何 UIView框架和边界
关于clipsToBounds(来源Apple doc)
将这个值设置为YES会导致子视图被剪切到边界 接收者。如果设置为NO,则其子视图的帧扩展到 接收器的可见边界没有被剪切。默认值为 不。
换句话说,如果一个视图的帧是(0,0,100,100),它的子视图是(90,90,30,30),你只能看到子视图的一部分。后者不会超出父视图的边界。
masksToBounds相当于clipsToBounds。这个属性应用于CALayer,而不是UIView。在底层,clipsToBounds调用masksToBounds。为了进一步的参考,看看如何是UIView的clipsToBounds和CALayer的masksToBounds之间的关系?
这篇文章有非常好的答案和详细的解释。我只是想说,在WWDC 2011的视频《理解UIKit渲染》中,从@4:22到20:10,有另一个关于帧、边界、中心、变换、边界原点的视觉表示的解释
看完以上答案,在此加上我的解读。
假设在线浏览,网页浏览器是你的框架,它决定在哪里和多大显示网页。浏览器的滚动条是你的边界。来源,决定网页的哪一部分将被显示。范围之内。起源很难理解。最好的学习方法是创建单视图应用程序,尝试修改这些参数并查看子视图如何变化。
- (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));
我认为如果你从CALayer的角度来思考,一切都更清楚了。
Frame并不是视图或层的独立属性,它是一个虚拟属性,由边界、位置(UIView的中心)和变换计算而来。
所以基本上图层/视图布局是由这三个属性(和anchorPoint)决定的,这三个属性中的任何一个都不会改变任何其他属性,比如改变transform不会改变边界。