视图的
frame,bounds和center
属性仅仅是存取方法,当操纵视图的frame
,实际上是在改变位于视图下方CALayer
的frame
,不能够独立于图层之外改变视图的frame
。
对于视图或者图层来说,
frame
并不是一个非常清晰的属性,它其实是一个虚拟属性,是根据bounds,position和transform
计算而来,所以当其中任何一个值发生改变,frame
都会变化。相反,改变frame
的值同样会影响到他们当中的值
基础属性frame、bounds、center/position
frame
指的是:该view
在父view
坐标系统中的位置和大小。(参照点是父亲的坐标系统)bounds
指的是:该view
在本身坐标系统中的位置和大小。(参照点是本身坐标系统)center
/position
指的是:该view
的锚点anchorPoint
在父view
坐标系统中的位置。(参照点是父亲的坐标系统)- 示例代码:显示橙色
View
的属性
NSLog(@"frame.size.width:%f",self.View2.frame.size.width);
NSLog(@"frame.size.height:%f",self.View2.frame.size.height);
NSLog(@"frame.origin.x:%f",self.View2.frame.origin.x);
NSLog(@"frame.origin.y:%f",self.View2.frame.origin.y);
NSLog(@"bounds.size.width:%f",self.View2.bounds.size.width);
NSLog(@"bounds.size.height:%f",self.View2.bounds.size.height);
NSLog(@"bounds.origin.x:%f",self.View2.bounds.origin.x);
NSLog(@"bounds.origin.y:%f",self.View2.bounds.origin.y);
NSLog(@"center.x:%f",self.View2.center.x);
NSLog(@"center.y:%f",self.View2.center.y);
- 输出结果:
2022-02-15 14:45:57.793675+0800 Music[10381:151978] frame.size.width:240.000000
2022-02-15 14:45:57.793755+0800 Music[10381:151978] frame.size.height:128.000000
2022-02-15 14:45:57.793816+0800 Music[10381:151978] frame.origin.x:174.000000
2022-02-15 14:45:57.793870+0800 Music[10381:151978] frame.origin.y:272.000000
2022-02-15 14:45:57.793908+0800 Music[10381:151978] bounds.size.width:240.000000
2022-02-15 14:45:57.793950+0800 Music[10381:151978] bounds.size.height:128.000000
2022-02-15 14:45:57.793998+0800 Music[10381:151978] bounds.origin.x:0.000000
2022-02-15 14:45:57.794027+0800 Music[10381:151978] bounds.origin.y:0.000000
2022-02-15 14:45:57.794070+0800 Music[10381:151978] center.x:294.000000
2022-02-15 14:45:57.794108+0800 Music[10381:151978] center.y:336.000000
UIView属性是CALayer属性的映射
center
其实就是映射CALayer
的posittion
frame
和bounds
分别映射CALayer
的frame
和bounds
UIView属性 | CALayer属性 | 属性说明 |
---|---|---|
frame | frame | 该view 在父view 坐标系统中的位置和大小。(参照点是父亲的坐标系统) |
bounds | bounds | bounds 指的是:该view 在本身坐标系统中的位置和大小。(参照点是本身坐标系统) |
center | position | 该view 的中心点在父view 坐标系统中的位置。(参照点是父亲的坐标系统) |
anchorPoint是独立的
@property CGPoint position; // 位置 设置anchorPoint在父控件的位置
@property CGPoint anchorPoint;// 定位点 以本身坐标系为核心
// 取值范围(0-1)默认(0.5,0.5)为中心
anchorPoint、position、frame
之间的关系:
frame
受position
和anchorPoint
(还有transform
)影响,修改任意一个都使frame
改变position
受frame
影响,两者相关绑定anchorPoint
不受任何因素影响
frame.origin.x = position.x - anchorPoint.x * bounds.size.width;
frame.origin.y = position.y - anchorPoint.y * bounds.size.height;
修改anchorPoint后,视图保持不变的解决方法
方法1
// 保存旧oldFrame的数值
CGRect oldFrame = view.frame;
// 修改锚点
view.layer.anchorPoint = newAnchorPoint;
// 这个时候position不变,anchorPoint改变,Frame改变,视图改变
// 把frame重置到原来的值,position跟着修改到新的位置,视图保持不变
view.frame = oldFrame;
方法2
// 可以直接修改position到正确的位置
CGPoint oldOrigin = view.frame.origin;
view.layer.anchorPoint = anchorPoint;
CGPoint newOrigin = view.frame.origin;
// 计算出position在x、y上的移动
CGPoint transition;
transition.x = newOrigin.x - oldOrigin.x;
transition.y = newOrigin.y - oldOrigin.y;
// position抵消掉x、y上的移动
view.center = CGPointMake (view.center.x - transition.x, view.center.y - transition.y);
transform使用的坑
frame
受position
、anchorPoint
、bound
和transform
影响,修改任意一个都使frame
改变frame
是一个动态属性,不要在视图变形(指的是transform
)之后继续使用frame
,因为它不能正确反映视图的实际位置,改为使用bounds + center
- 官方文档是这么说的👇