frame bounds center的区别

来源:UIView frame, bounds and center

首先明确一个问题:frameboundscenter 是什么及他们之间的关系。

Frame:一个 viewframe 是该 view 相对于 superview 坐标系的矩形位置,默认的起始点是左上点。
Bounds: 表示该 view 在自身坐标系的矩形。
Center: 一个 center 是一个 CGPoint,表示该 view 的中心点相对于 superview 的坐标系的位置。

这几个属性的关系如下:

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

NOTE:view 被旋转后上面的关系不成立。具体参考下面的例子:

frame bounds center的区别_第1张图片

frame 可以在 superview 中改变 view 的位置或大小。通常用于 superview,比如当创建指定 subview 时:

// 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 中画一个 view 通常需要使用 bounds。典型的例子是在一个 view 中画一个 subview,此时需要知道 superviewbounds

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];

当改变一个 view 的 bounds 时发生不同的行为,比如,如果改变 bounds 的大小,frame 也会改变。这些改变是围绕 viewcenter 发生的(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));

输出如下结果,其中 frame 改变,而 center 没有改变:

Old Frame {{20, 20}, {360, 360}}
Old Center {200, 200}
New Frame {{10, 10}, {380, 380}}
New Center {200, 200}

此外,如果改变 bounds 的原点,就会改变内部坐标系的原点。默认的原点是 (0.0, 0.0)。比如,改变 view1 的原点,会发现 view2 的左上点与 view1 的左上点重合了,这个变化是显而易见的。

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

原点不仅表示 view 相对于 superview 的位置,也描述了 bounds 中心的位置。

最后,boundsorigin 不是同一个概念,他们都影响 viewframe

示例代码:

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]));

关系如图:


frame bounds center的区别_第2张图片

如果改变 [self view]bounds

// previous code here...
CGRect rect = [[self view] bounds];
rect.origin.x += 30.0f;
rect.origin.y += 20.0f;
[[self view] setBounds:rect];

变化如下:


frame bounds center的区别_第3张图片

[self view] 的左上角现在的位置是 (30.0, 20.0) ,同时 view1frame 原点开始于 (30.0, 20.0),他们是一致的。

Additional references

  • UIView Geometry
  • UIView Frames and Bounds

关于 clipsToBoundsApple 的文档如下:

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.

换句话说,如果一个 viewframe(0, 0, 100, 100),而 subview(90, 90, 30, 30),就只能看到 subview 的一部分。超过 parent viewbounds 的部分不会显示。

masksToBounds 等于 clipsToBounds,不同于 clipsToBounds 用于 UIViewmasksToBounds 属性应用于 CALayer。 实际上,clipsToBounds 调用 masksToBounds

更多可以参考How is the relation between UIView's clipsToBounds and CALayer's masksToBounds?。

你可能感兴趣的:(frame bounds center的区别)