在iOS中我们经常会对控件位置调整,利用到了bounds和frame,但是一直没搞懂他俩的区别,今天记录一下。
下面通过一段简单的代码对比一下。
//
// ViewController.m
// frameAndbounds
//
// Created by 差不多先生 on 2022/10/3.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
view1.backgroundColor = [UIColor redColor];
[self.view addSubview:view1];
NSLog(@"view1 frame:%@========view1 bounds:%@",NSStringFromCGRect(view1.frame),NSStringFromCGRect(view1.bounds));
UIView* view2 = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
view2.backgroundColor = [UIColor yellowColor];
[view1 addSubview:view2];
NSLog(@"view2 frame:%@========view2 bounds:%@",NSStringFromCGRect(view2.frame),NSStringFromCGRect(view2.bounds));
}
@end
我们往根视图添加了view1,再在view1上添加了view2.
根据对比frame和bounds的数值,很容易理解,frame对应的原点是根据父视图决定的,而bounds的原点是根据自身决定的,也就是本地。
下面我们修改view1的bounds。
[view1 setBounds:CGRectMake(-20, -20, 200, 200)];
我们对view1修改bounds却让view2移动了。
这是因为setBounds的作用是:强制将自己(view1)本地坐标系的原点改为(-20,-20)。这个(-20,-20)是相对view1的父view(self.view)偏移的。也就是向左上角偏移。
那么在view1的坐标系中(0,0)这个点是需要向右下各偏移20。
因为view1的subview(view2)的frame参照的坐标系是父view(view1)的bounds设置的,而此时view2的frame设置为(0,0),就会导致view2向右下各偏移20。如上图所示。
所以,bounds的有这么一个特点:
它是参考自己坐标系,它可以修改自己坐标系的原点位置,进而影响到“子view”的显示位置。
其实bounds我们一直在使用,就是我们使用scrollview的时候。
我们设置了一个整页屏幕,但是在滑动时,可以显示图片之外的东西,就是因为scrollview在不断改变自己的bounds,从而改变scrollview上的子view的frame,让他们的frame始终在最顶级view(window)的frame内部,这样我们就可以始终看到内容了。
在滚动时image和scrollview的frame都没变,唯一在不断改变的是scrollview的contentoffset和bounds,而且两者完全相同。
//
// ViewController.m
// frameAndbounds
//
// Created by 差不多先生 on 2022/10/3.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
view1.backgroundColor = [UIColor redColor];
[self.view addSubview:view1];
NSLog(@"view1 frame:%@========view1 bounds:%@",NSStringFromCGRect(view1.frame),NSStringFromCGRect(view1.bounds));
[view1 setBounds:CGRectMake(-20, -20, 400, 400)];
NSLog(@"view1 frame:%@========view1 bounds:%@",NSStringFromCGRect(view1.frame),NSStringFromCGRect(view1.bounds));
UIView* view2 = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
view2.backgroundColor = [UIColor yellowColor];
[view1 addSubview:view2];
NSLog(@"view2 frame:%@========view2 bounds:%@",NSStringFromCGRect(view2.frame),NSStringFromCGRect(view2.bounds));
}
@end
假设设置了控件的bounds大于frame,那么此时会导致frame被撑大,frame的x,y,width,height都会改变。