frame和bounds的区别

首先,我们来看一下iOS特有的坐标系,在iOS坐标系中以左上角为坐标原点,往右为X正方向,往下是Y正方向如下图:

 

bounds和frame都是属于CGRect类型的结构体,系统的定义如下,包含一个CGPoint(起点)和一个CGSize(尺寸)子结构体。

struct CGRect {
    CGPoint origin;
    CGSize size;
};

origin决定了view的起点,size决定View的尺寸。

1.frame

frame是每个view必备的属性,表示view在父view坐标系统中的位置和大小,参照点是父视图的坐标系统。

示例代码:

UIView *viewA = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 300, 300)];
[viewA setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:viewA];
NSLog(@"viewA - %@",NSStringFromCGRect(viewA.frame));

UIView *viewB = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
[viewB setBackgroundColor:[UIColor yellowColor]];
[viewA addSubview:viewB];
NSLog(@"viewB - %@",NSStringFromCGRect(viewB.frame));

UIView *viewC = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[viewC setBackgroundColor:[UIColor redColor]];
[self.view addSubview:viewC];
NSLog(@"viewC - %@",NSStringFromCGRect(viewC.frame));

打印结果:

2018-01-14 21:35:16.196389+0800 frame & bounds[1485:121325] viewA - {{50, 50}, {300, 300}}
2018-01-14 21:35:16.196647+0800 frame & bounds[1485:121325] viewB - {{50, 50}, {200, 200}}
2018-01-14 21:35:16.196802+0800 frame & bounds[1485:121325] viewC - {{100, 100}, {200, 200}}
复制代码

效果图:

 

以上可以看出,viewB和viewC的起点重合,但是从打印结果来看,viewB的起点为(50,50),而viewCde起点为(100,100)。原因就是frame中的位置是以父视图的坐标系为标准来确定当前视图的位置,viewB的父视图为viewA,viewC的父视图为self.view,而由于viewA的起点为(50,50),所以viewB与viewC起点才会重合。

2.bounds

bounds也是每个view都有的属性,这个属性我们一般不进行设置,表示view在本地坐标系统中的位置和大小。bounds的参照点是本地坐标系统。如果我们对上例打印bounds,将会得到以下结果:

2018-01-14 22:03:44.385207+0800 frame & bounds[1635:140821] viewA - {{0, 0}, {300, 300}}
2018-01-14 22:03:44.385482+0800 frame & bounds[1635:140821] viewB - {{0, 0}, {200, 200}}
2018-01-14 22:03:44.385646+0800 frame & bounds[1635:140821] viewC - {{0, 0}, {100, 100}}

因为我们并没有设置bounds值,那么,bounds到底有什么作用呢。这里强调,每个视图都有自己的坐标系,且这个坐标系默认以自身的左上角为坐标原点,所有子视图以这个坐标系的原点为基准点。bounds的位置代表的是子视图看待当前视图左上角的位置,bounds的大小代表当前视图的大小。原则如下:

  • 更改bounds中的位置对于当前视图没有影响,相当于更改了当前视图的坐标系,对于子视图来说当前视图的左上角已经不再是(0,0), 而是改变后的坐标,坐标系改了,那么所有子视图的位置也会跟着改变。
  • 更改bounds的大小,bounds的大小代表当前视图的长和宽,修改长宽后,中心点继续保持不变, 长宽进行改变,通过bounds修改长宽看起来就像是以中心点为基准点对长宽两边同时进行缩放。

以下给出例子详细讨论。

3.两者的区别

3.1 origin的区别

如下图:

此时,如果我们把ViewA的bounds改为(0,100),结果如下:

我们始终要清楚,父视图的bounds的位置代表的是子视图看待当前视图左上角的位置。 bounds遵守的原则一中,更改bounds中的位置对于当前视图(ViewA)没有影响,相当于更改了ViewA的坐标系,但是子视图(ViewB)不同,对于ViewB来说ViewA的左上角已经不再是(0,0), 而是(0,100),所以对于ViewB来说,ViewA坐标系的原点其实是在红色箭头所指处的上方100处,而此时ViewB的frame.origin为(200,100),所以ViewB的上边与ViewA上边重合。

如果我们更改ViewA的bounds为(200,0),同理(可以自己思考试试),结果如下:

 

3.2 size的区别

frame的size直接决定了view的大小,而bounds的size修改后,view的中心点不变,长宽以中心点进行缩放。

如下例:

UIView *viewA = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 240)];
[viewA setBackgroundColor:[UIColor grayColor]];
[self.view addSubview:viewA];

UIView *viewB = [[UIView alloc] initWithFrame:CGRectMake(100, 50, 160, 120)];
[viewB setBackgroundColor:[UIColor blueColor]];
[viewA addSubview:viewB];

//viewB设置size(320,160)
[viewB setBounds:CGRectMake(0, 0, 320, 240)];

结果如下:

 

 

 

第二个图为设置了size之后的结果,viewB左上点距离viewA显然不为(100,50),而是进行了基于viewB视图中心点的缩放操作。

4.总结

  • frame不管对于位置还是大小,改变的都是自己本身。
  • frame的位置是以父视图的坐标系为参照,从而确定当前视图在父视图中的位置。
  • frame的大小改变时,当前视图的左上角位置不会发生改变,只是大小发生改变。
  • bounds改变位置时,改变的是子视图的位置,自身没有影响;其实就是改变了本身的坐标系原点,默认本身坐标系的原点是左上角。
  • bounds的大小改变时,当前视图的中心点不会发生改变,当前视图的大小发生改变,看起来效果就想缩放一样。

position和anchorPosition
通过声明我们可以发现它们都是CGPoint类型。此刻我们把CALayer看作是一张打印纸被一根图钉钉在桌面上(相当于父界面元素的CALayer),可以想像这张打印纸可以绕着这根图钉旋转。那么图钉相对于打印纸的位置就可以用anchorPosition来描述(默认的anchorPosition为(0.5,0.5)),而这根图钉在桌面上的位置便是position。anchorPosition和position永远是重合的, 只不过一个是相对于外界的(position),而一个是相对自身的(anchorPosition)( https://blog.csdn.net/E20914053/article/details/49950307 )


position的坐标是父坐标下的位置,而anchorPosition是钉子钉的那个点在子坐标下的比例(范围:0~1的浮点数)
例子:用上图举例子。比如说我想钉住B视图中的(10,10)这个点,那么我的B.position = (B.frame.x+10,B.frame.y+10) = (210,110)

**例如添加一个红色图层到绿色图层上,红色图层显示到什么位置上,有position属性决定的,假设红色图层的position是(100, 100),:
(1)红色图层的anchorPoint是(0,0),那么显示的情况如下:

在这里插入图片描述

(2)红色图层的anchorPoint是(0.5, 0.5) , 那么显示如下:

在这里插入图片描述

(3)红色图层的anchorPoint是(1, 1), 显示如下:

在这里插入图片描述

(4)红色图层的anchorPoint是(0.5, 0),显示如下:

在这里插入图片描述

(5)如果红色图层的anchorPoint是(1,0.5),显示如下:

在这里插入图片描述

center和position
center:描述当前界面元素的中心点在其父界面元素中的位置。
例子:
B.center = (B.frame.size.x+0.5*B.bounds.size.width,B.frame.size.y+0.5*B.bounds.size.height)=(300,225)

position是layer相对superLayer坐标空间的位置,很显然,这里的位置是根据anchorPoint来确定的。 请看下面的公式:

position.x = frame.origin.x + anchorPoint.x * bounds.size.width;

position.y = frame.origin.y + anchorPoint.y * bounds.size.height;

或者说, 进而推导出frame的计算公式为:

frame.origin.x = position.x - anchorPoint.x * bounds.size.width;  
frame.origin.y = position.y - anchorPoint.y * bounds.size.height;

当你设置图层的frame属性的时候,position点的位置(也就是position坐标)根据锚点(anchorPoint)的值来确定,
而当你设置图层的position属性的时候,frame的orgin坐标会根据锚点(anchorPoint)来确定。

frame和position的相互影响的计算方式就是上面的方法.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值