iOS——frame bounds
前言
在iOS中我们经常会对控件位置调整,利用到了bounds和frame,但是一直没搞懂他俩的区别,今天记录一下。
frame和bounds简介
- frame: 该view在父view坐标系统中的位置和大小。(参照点是,父亲的坐标系统)
- bounds:该view在本地坐标系统中的位置和大小。(参照点是,本地坐标系统,就相当于ViewB自己的坐标系统,以0,0点为起点)。
下面通过一段简单的代码对比一下。
//
// 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的应用
其实bounds我们一直在使用,就是我们使用scrollview的时候。
我们设置了一个整页屏幕,但是在滑动时,可以显示图片之外的东西,就是因为scrollview在不断改变自己的bounds,从而改变scrollview上的子view的frame,让他们的frame始终在最顶级view(window)的frame内部,这样我们就可以始终看到内容了。
在滚动时image和scrollview的frame都没变,唯一在不断改变的是scrollview的contentoffset和bounds,而且两者完全相同。
bouns大于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));
[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都会改变。
- 新的frame的size等于bound的size。
- 新的frame.x = 旧frame.x - (bounds.size.witdh - 旧frame.size.width)/2
- 新的frame.y = 旧frame.y - (bounds.size.height - 旧frame.size.height)/2