文章目录
- 前言
- frame
- bounds
- 两者区别
- size的区别
- 总结
前言
在学习响应者链的过程中用到了frame与bounds的混用,这两个属性经常出现在我们的开发中,特别撰写一篇博客分析区别
首先,我们来看一下iOS特有的坐标系,在iOS坐标系中以左上角为坐标原点,往右为X正方向,往下是Y正方向如下图:
我们来看一下frame与bounds在文件中的定义
bounds
默认边界为原点0,frame大小。可以做成动画
frame
可以做成动画。如果视图被转换,不要使用frame,因为它不能正确反映视图的实际位置。使用bounds + center代替
。
同时可以看到他们都是CGRect
结构体
struct CGRect {
CGPoint origin;
CGSize size;
};
origin
决定了view
的起点,size
决定View
的尺寸
frame
frame
描述的是视图相对于它的父视图的坐标系统中的位置和大小。它包含一个CGRect
值,定义视图的原点位置和宽高。
- 坐标系:父视图的坐标系。
- 内容:包含视图的原点相对于父视图的位置,以及视图的宽度和高度。
- 应用:适合在父视图中设置视图的位置和大小。
来看一段Demo
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));
输出:
以上可以看出,viewB和viewC的起点重合
但是从打印结果来看,viewB的起点为(50,50),而viewC的起点为(100,100)。
原因就是frame中的位置是以父视图的坐标系为标准来确定当前视图的位置
viewB的父视图为viewA,viewC的父视图为self.view,而由于viewA的起点为(50,50),所以viewB与viewC起点才会重合。
bounds
我们再打印一下bounds
UIView *viewA = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 300, 300)];
[viewA setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:viewA];
NSLog(@"viewA - %@",NSStringFromCGRect(viewA.bounds));
UIView *viewB = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
[viewB setBackgroundColor:[UIColor yellowColor]];
[viewA addSubview:viewB];
NSLog(@"viewB - %@",NSStringFromCGRect(viewB.bounds));
UIView *viewC = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[viewC setBackgroundColor:[UIColor redColor]];
[self.view addSubview:viewC];
NSLog(@"viewC - %@",NSStringFromCGRect(viewC.bounds));
可以看到bounds的起点都是0
这也符合文档中的说明默认边界为原点0,frame大小。可以做成动画
每个视图都有自己的坐标系,且这个坐标系默认以自身的左上角为坐标原点,所有子视图以这个坐标系的原点为基准点。
bounds
的位置代表的是子视图看待当前视图左上角的位置,bounds
的大小代表当前视图的大小。
- 修改frame会改变视图在父视图中的位置。
- 修改bounds不会改变视图在父视图中的位置,只会改变其内部内容的绘制区域,也就是会改变子视图的位置、
两者区别
此时,如果我们把ViewA
的bounds
改为(0,100),结果如下:
此时父视图左上角不再是(0,0),而是(0,50),因此子视图才会往上移动
size的区别
frame的size直接决定了view的大小,而bounds的size修改后,view的中心点不变,长宽以中心点进行缩放
。
看Demo:
UIView *viewA = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 300, 300)];
[viewA setBackgroundColor:[UIColor blueColor]];
viewA.bounds = CGRectMake(50, 50, 300, 300);
[self.view addSubview:viewA];
NSLog(@"viewA - %@",NSStringFromCGRect(viewA.bounds));
修改bounds为CGRectMake(50, 50, 100, 100)
中心点没变,只是中心点进行了缩放
总结
坐标系不同:
frame
:父视图坐标系,用于确定视图在父视图中的位置。
bounds
:自身坐标系,用于描述视图内容区域的布局。
位置与布局:
frame
用于确定视图在父视图中的整体位置和大小。
bounds
修改origal自身不变化,会影响子视图,修改size以自身中心点进行缩放
参考博客:frame与bounds的区别详解