简介
frame是父视图坐标系中的位置和大小;bounds是自身视图坐标系中的位置和大小。
其中,不管是frame还是bounds,大小这点一样,代表矩形的长和宽,这个很好理解。可是,原点位置呢?frame很好理解。但是bounds呢?什么叫做自身坐标系?真的是太难理解了。
frame和bounds的区别
这篇文章中的有一句话说的很对:
它是参考自己坐标系,它可以修改自己坐标系的原点位置,进而影响到“子view”的显示位置。
实验场景
默认的self.view设置为蓝色;父view设置为红色;子view设置为黄色。代码如下:
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UIView *fatherView;
@property (nonatomic, strong) UIView *sonView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.fatherView = [[UIView alloc] init];
self.sonView = [[UIView alloc] init];
[self.fatherView addSubview:self.sonView];
[self.view addSubview:self.fatherView];
// 父视图
self.fatherView.backgroundColor = [UIColor redColor];
// 子视图
self.sonView.backgroundColor = [UIColor yellowColor];
// 背景视图
self.view.backgroundColor = [UIColor blueColor];
}
- (void)viewWillLayoutSubviews {
self.fatherView.frame = CGRectMake(100, 100, 200, 200);
self.sonView.bounds = CGRectMake(0, 0, 100, 100);
NSLog(@"fatherView frame:%@ ====== fatherView bounds:%@", NSStringFromCGRect(self.fatherView.frame), NSStringFromCGRect(self.fatherView.bounds));
NSLog(@"sonView frame:%@ ====== sonView bounds:%@", NSStringFromCGRect(self.sonView.frame), NSStringFromCGRect(self.sonView.bounds));
}
@end
在这里,位置的设置就两句话:
self.fatherView.frame = CGRectMake(100, 100, 200, 200);
self.sonView.bounds = CGRectMake(0, 0, 100, 100);
父view设置了frame,子view设置了bounds。实际效果如下:
效果图打印信息如下:
fatherView frame:{{100, 100}, {200, 200}} ====== fatherView bounds:{{0, 0}, {200, 200}}
sonView frame:{{-50, -50}, {100, 100}} ====== sonView bounds:{{0, 0}, {100, 100}}
通过打印信息和图片位置的对比,父view可以理解;子view的大小也没问题,可是子view的原点(-50,-50)是怎么来的?
改动1:修改子view的bounds原点
比如self.sonView.bounds = CGRectMake(50, 50, 100, 100);
或者self.sonView.bounds = CGRectMake(20, 30, 100, 100);
... ...
不论怎么改,只要不改大小,父子视图位置关系始终不变。
这说明bounds的原点不会影响自己的位置;
改动2:修改子view的bounds大小
既然子view的bounds的原点不影响自己在父view中的位置,那么就保持(0,0)不变,那么就修改bounds的大小试试。
做了几次实验,结果如下:
self.sonView.bounds = CGRectMake(0, 0, 50, 50);
// sonView frame:{{-25, -25}, {50, 50}}
self.sonView.bounds = CGRectMake(0, 0, 100, 100);
// sonView frame:{{-50, -50}, {100, 100}}
self.sonView.bounds = CGRectMake(0, 0, 200, 200);
// sonView frame:{{-100, -100}, {200, 200}}
总感觉原点的位置是长宽的一半,然后加个负号;比如w=100时,x=-50
是巧合吗?h=100时,y= -50
子view加上frame
考虑到子view没有加frame,只是加了bounds。那么猜想,子view默认的frame应该是全0,也就是self.sonView.frame = CGRectMake(0, 0, 0, 0);
那么,加上bounds之后,子view的frame的原点该怎么确定呢?
- 公式猜想:
self.sonView.frame = CGRectMake(fx, fy, fw, fh);
self.sonView.bounds = CGRectMake(bx, by, bw, bh);
经过以上两个语句之后,大小是bw和bh,这个会覆盖,没有疑问,也很好理解。但是x和y呢? 有如下公式:
x = fx + (fw - bw)/ 2;
y = fy + (fh - bh)/ 2;
简单讲就是如果bounds的大小变了,就是偏移大小变化的一半。
比如:-50 = 0 + (0 - 100)/ 2
- 又实验了几组数据,结果如下:
self.sonView.frame = CGRectMake(0, 0, 80, 50);
self.sonView.bounds = CGRectMake(0, 0, 100, 100);
// sonView frame:{{-10, -25}, {100, 100}}
// x: -10 = 0 + (80 - 100) / 2
// y: -25 = 0 + (50 - 100) / 2
self.sonView.frame = CGRectMake(0, 30, 80, 150);
self.sonView.bounds = CGRectMake(0, 0, 100, 100);
// sonView frame:{{-10, 55}, {100, 100}}
// x: -10 = 0 + (80 - 100) / 2
// y: 55 = 30 + (150 - 100) / 2
self.sonView.frame = CGRectMake(-10, 30, 180, 150);
self.sonView.bounds = CGRectMake(0, 0, 100, 100);
// sonView frame:{{30, 55}, {100, 100}}
// x: 30 = -10 + (180 - 100) / 2
// y: 55 = 30 + (150 - 100) / 2
实验了几组数据,基本吻合。
修改父view的bounds
-
大小只改变父view自己,对于子view没有影响。
-
原点不会改变子view的frame,但是会改变子view的位置。
-
父view不改bounds,情况很正常
self.fatherView.frame = CGRectMake(100, 100, 200, 200);
self.sonView.frame = CGRectMake(0, 0, 100, 100);
// sonView frame:{{0, 0}, {100, 100}}
正常图片
- 父view修改bounds的原点,子view偏了
self.fatherView.frame = CGRectMake(100, 100, 200, 200);
self.fatherView.bounds = CGRectMake(20, 40, 200, 200);
self.sonView.frame = CGRectMake(0, 0, 100, 100);
// sonView frame:{{0, 0}, {100, 100}}
子view偏了
原来被认为是(0,0)的地方,现在变成了(20,40)。所以(0,0)跑左上角去了。
网友评论