UIView框架,边界和中心

Lor*_*o B 315 objective-c frame uiview bounds ios

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

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

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

最后,bounds是相对于视图本身.它会更改视图的可绘制区域.

你能给约之间的关系更多信息framebounds?那些clipsToBoundsmasksToBounds属性呢?

Lor*_*o B 570

由于我问过的问题已多次出现,我将提供详细的答案.如果您想添加更多正确的内容,请随意修改它.

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

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

边界视图bounds(CGRect)表示其自身坐标系中的视图矩形.

中心 A centerCGPointsuperview坐标系表示的,它决定了视图的精确中心点的位置.

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

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

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

  • frame.size = bounds.size

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

框架,边界和中心

使用frame允许您在其中重新定位和/或调整视图大小superview.通常可以从a中使用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];
Run Code Online (Sandbox Code Playgroud)

当你需要在里面绘制坐标时,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];
Run Code Online (Sandbox Code Playgroud)

更改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));
Run Code Online (Sandbox Code Playgroud)

此外,如果你改变bounds origin你改变origin它的内部坐标系.默认情况下,origin位于(0.0, 0.0)(左上角).例如,如果您更改了originfor,view1您可以看到(如果需要,请注释前面的代码),现在左上角view2触摸了view1一个.动机很简单.你说view1,它的左上角是现在的位置(20.0, 20.0),但由于view2frame origin距离开始(20.0, 20.0),他们将一致.

CGRect frame = view1.bounds;
frame.origin.x += 20.0f;
frame.origin.y += 20.0f;
view1.bounds = frame; 
Run Code Online (Sandbox Code Playgroud)

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

最后,boundsorigin不是相关的概念.两者都允许导出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]));
Run Code Online (Sandbox Code Playgroud)

相对的形象.

在此输入图像描述

相反,如果我更改[self view]如下所示的界限会发生什么.

// previous code here...
CGRect rect = [[self view] bounds];
rect.origin.x += 30.0f;
rect.origin.y += 20.0f;
[[self view] setBounds:rect];
Run Code Online (Sandbox Code Playgroud)

相对的形象.

在此输入图像描述

在这里你说它的[self view]左上角现在位于(30.0,20.0)位置,但由于view1帧的起点是从(30.0,20.0)开始,它们将重合.

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

关于clipsToBounds(来源Apple doc)

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

换句话说,如果视图frame(0, 0, 100, 100)并且其子视图是(90, 90, 30, 30),则您将只看到该子视图的一部分.后者不会超过父视图的范围.

masksToBounds相当于clipsToBounds.而不是a UIView,此属性应用于a CALayer.在引擎盖下,clipsToBounds打电话masksToBounds.如需进一步参考,请查看UIView的clipsToBounds和CALayer的masksToBounds之间的关系如何?.


Sur*_*gch 131

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

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

为了帮助我记住边界,我想到了篮球场的界限.篮球就在球场内的某个地方,就像视线边界的坐标系在视野内一样.(court = view,basketball/players =视图内容)

与框架一样,view.center也在superview的坐标中.

框架与边界 - 示例1

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

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

Bounds 
    origin = (0, 0)
    width = 80
    height = 130
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


例2

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

Bounds 
    origin = (0, 0)
    width = 80
    height = 130
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


例3

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

Bounds 
    origin = (0, 0)
    width = 80
    height = 130
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


例4

这与示例2相同,除了这次显示视图的整个内容,如果它没有被剪切到视图的边界,它将看起来像.

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

Bounds 
    origin = (0, 0)
    width = 80
    height = 130
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


例5

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

Bounds 
    origin = (280, 70)
    width = 80
    height = 130
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

再次,请参阅此处获取更多详细信息的答案.

  • 谢谢Suragch.框架和界限差异真的非常清晰.我非常感谢你的努力. (2认同)

Erb*_* Mo 88

我发现这个图像对于理解框架,边界等最有帮助.

在此输入图像描述

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

  • 一张价值千言万语的图片. (14认同)
  • 最好的解释 (3认同)

coo*_*eet 5

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

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

因此,基本上,图层/视图布局实际上是由这三个属性(和anchorPoint)决定的,并且这三个属性中的任何一个都不会更改任何其他属性,例如更改变换不会更改边界。