由于我提出的问题已被多次看到,因此我将提供详细的答案。如果您想添加更多正确的内容,请随时修改它。
首先回顾一下这个问题:框架、边界和中心以及它们之间的关系。
Frame 视图的frame (CGRect) 是其矩形在superview 坐标系中的位置。默认情况下,它从左上角开始。
边界视图的bounds (CGRect) 在其自己的坐标系中表示视图矩形。
中心center 是一个CGPoint,以superview 的坐标系表示,它确定了视图的确切中心点的位置。
取自 UIView + position 这些是先前属性之间的关系(它们在代码中不起作用,因为它们是非正式方程):
注意:如果视图旋转,则这些关系不适用。有关更多信息,我建议您查看以下图片,该图片来自 The Kitchen Drawer,基于 Stanford CS193p 课程。致谢@Rhubarb。
使用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];
当您需要在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];
当您更改视图的bounds 时会发生不同的行为。
例如,如果您更改 bounds size,则 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));
此外,如果您更改bounds origin,您将更改其内部坐标系的origin。默认情况下,origin 位于(0.0, 0.0)(左上角)。例如,如果您将origin 更改为view1,您可以看到(如果需要,可以评论前面的代码)现在view2 的左上角触及view1 之一。动机很简单。你对view1说它的左上角现在在(20.0, 20.0)的位置,但是由于view2的frameorigin是从(20.0, 20.0)开始的,它们会重合。
CGRect frame = view1.bounds;
frame.origin.x += 20.0f;
frame.origin.y += 20.0f;
view1.bounds = frame;
origin 表示view 在其superview 中的位置,但描述了bounds 中心的位置。
最后,bounds 和 origin 不是相关概念。两者都允许导出视图的frame(参见前面的方程式)。
View1 的案例研究
这是使用以下 sn-p 时会发生的情况。
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]));
相对图像。
如果我像下面这样更改[self view] 边界会发生什么。
// 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)开始,它们会重合。
其他参考资料(如果需要,可以使用其他参考资料进行更新)
关于clipsToBounds(来源 Apple 文档)
将此值设置为 YES 会导致子视图被裁剪到边界
的接收器。如果设置为 NO,则其框架超出
接收器的可见边界不会被剪裁。默认值为
没有。
换句话说,如果一个视图的frame 是(0, 0, 100, 100) 并且它的子视图是(90, 90, 30, 30),您将只能看到该子视图的一部分。后者不会超出父视图的范围。
masksToBounds 等价于clipsToBounds。此属性应用于CALayer,而不是UIView。在后台,clipsToBounds 调用 masksToBounds。如需更多参考,请查看How is the relation between UIView's clipsToBounds and CALayer's masksToBounds?。