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.frame - %@",NSStringFromCGRect(viewA.frame));
NSLog(@"viewA.bounds - %@",NSStringFromCGRect(viewA.bounds));
UIView *viewB = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
[viewB setBackgroundColor:[UIColor yellowColor]];
[viewA addSubview:viewB];
NSLog(@"viewB.frame - %@",NSStringFromCGRect(viewB.frame));
NSLog(@"viewB.bounds - %@",NSStringFromCGRect(viewB.bounds));
UIView *viewC = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[viewC setBackgroundColor:[UIColor redColor]];
[self.view addSubview:viewC];
NSLog(@"viewC.frame - %@",NSStringFromCGRect(viewC.frame));
NSLog(@"viewC.bounds - %@",NSStringFromCGRect(viewC.bounds));
打印结果:
2024-08-01 21:05:53.857358+0800 frame和bounds[2744:130774] viewA.frame - {{50, 50}, {300, 300}}
2024-08-01 21:05:53.857419+0800 frame和bounds[2744:130774] viewA.bounds - {{0, 0}, {300, 300}}
2024-08-01 21:05:53.857497+0800 frame和bounds[2744:130774] viewB.frame - {{50, 50}, {200, 200}}
2024-08-01 21:05:53.857542+0800 frame和bounds[2744:130774] viewB.bounds - {{0, 0}, {200, 200}}
2024-08-01 21:05:53.857605+0800 frame和bounds[2744:130774] viewC.frame - {{100, 100}, {100, 100}}
2024-08-01 21:05:53.857644+0800 frame和bounds[2744:130774] viewC.bounds - {{0, 0}, {100, 100}}
viewB和viewC的起点重合,但是从打印结果来看,viewB的起点为(50,50),而viewC起点为(100,100)。原因就是frame中的位置是以父视图的坐标系为标准来确定当前视图的位置,viewB的父视图为viewA,viewC的父视图为self.view,而由于viewA的起点为(50,50),所以viewB
与viewC
起点才会重合。
2,bounds
bounds是每个view都有的属性,我们一般不进行设置,表示view在本地坐标系系统中的位置和大小。参照点是本地坐标系系统。
2024-08-01 21:05:53.857419+0800 frame和bounds[2744:130774] viewA.bounds - {{0, 0}, {300, 300}}
2024-08-01 21:05:53.857542+0800 frame和bounds[2744:130774] viewB.bounds - {{0, 0}, {200, 200}}
2024-08-01 21:05:53.857644+0800 frame和bounds[2744:130774] viewC.bounds - {{0, 0}, {100, 100}}
因为我们没有设置bounds值,我们打印的每个view的起点都是(0,0)。
bounds的作用是什么?
每个视图都有自己的坐标系,且每个坐标系默认以自身的左上角为坐标原点,所有视图以这个坐标系的原点为基准点。bounds的位置代表的是子视图看待当前视图左上角的位置,bounds的大小代表当前视图的大小。原则如下:
1,更改bounds
中的位置对于当前视图没有影响,相当于更改了当前视图的坐标系,对于子视图来说,当前视图的左上角已经不再是(0,0),而是更改后的坐标,坐标系改变后了,那么所有的子视图的位置也会跟着改变。
2,更改bounds
的大小,bounds的大小代表当前视图的长和宽,修改长和宽后,中心点继续保持不变,长宽进行改变,通过bounds修改长宽看起来就像是以中心点为基总点对长宽两边同时进行缩放。
3,fram和bounds的区别
3.1origin的区别
我们修改viewA的bounds
[viewA setBounds:CGRectMake(25, 25, 300, 300)];
我们再只在修改viewB的frame
UIView *viewB = [[UIView alloc] initWithFrame:CGRectMake(25, 25, 200, 200)];
我们发现出现了同样的效果
通过改变viewA
的坐标系原点,会造成子视图viewB
的移动,这里的移动是靠viewB
的Frame
的起点相对于父视图的bounds的起点(父视图本身的坐标系)。
同样我们不改变父视图的坐标系,改变子视图的frame的起点也能达到相同的效果。
3.2size的区别
我们改变viewB的bounds
[viewB setBounds:CGRectMake(0, 0, 250, 250)];
我们发现viewB的左上角也扩大了
frame
的size直接决定了view的大小,而bounds
的size修改后,view的中心点不变,长宽以中心点进行缩放
总结:
- frame不管对于位置还是大小,改变的都是自己本身。fram的位置是一父视图的坐标系为参照系,从而确定当前视图在父视图中的位置。frame的大小改变时,当前视图的左上角不会改变,只是大小改变。
- bounds改变位置时,改变的是子视图的位置,自身没有影响,改变了本身的坐标系原点,默认是坐标系的原点是左上角。bounds改变大小时,当前视图的中心点不会改变,当前视图的大小发生改变,以中心点实现缩放的效果。