iOS——frame和bounds的区别

把frame理解为占用区域,把bounds理解为边界。View在旋转过程中,其实自己的坐标系统并没有发生改变,bounds中的origin只能通过setBounds方法修改。

frame 定义了视图在其父视图坐标系统中的位置和大小。其坐标系是相对于俯视图的坐标系。

bounds 定义了视图自身坐标系统中的位置和大小。其坐标系是相对于自己本身视图的坐标系。

UIView.h中的注释:

objc 复制代码
// 如果视图进行了变换,不要使用 frame,因为它不会正确反映视图的实际位置。使用 bounds + center 代替。
@property(nonatomic) CGRect frame;

// 如果非恒等变换,请使用 bounds/center 而不是 frame。
@property(nonatomic) CGRect bounds;      // 默认 bounds 是原点为零,大小为 frame 的大小。
@property(nonatomic) CGPoint center;      // center 是 frame 的中心,相对于 anchorPoint。
  • bounds的x,y是根据自己的坐标系统而言的。没错,每个view都有自己的坐标系。以自己左上角点为坐标原点。所以bounds的x,y默认为(0,0),除非调用setBounds方法;
  • frame的size不一定等于bounds的size,在旋转后它们的size就不一样了。

有如下示例:

objc 复制代码
- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *animateButton = [UIButton buttonWithType:UIButtonTypeSystem];
    animateButton.frame = CGRectMake(100, 250, 100, 50);
    [animateButton setTitle:@"Animate" forState:UIControlStateNormal];
    [animateButton addTarget:self action:@selector(startAnimation) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:animateButton];
    
    self.fView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    [self.view addSubview:self.fView];
    self.fView.backgroundColor = [UIColor orangeColor];
    
    self.sView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
    [self.fView addSubview:self.sView];
    self.sView.backgroundColor = [UIColor blueColor];
    
    NSLog(@"Bounds:");
    NSLog(@"fView x:%f; sView x:%f", self.fView.bounds.origin.x, self.sView.bounds.origin.x);
    NSLog(@"fView y:%f; sView y:%f", self.fView.bounds.origin.y, self.sView.bounds.origin.y);
    
    NSLog(@"frame:");
    NSLog(@"fView x:%f; sView x:%f", self.fView.frame.origin.x, self.sView.frame.origin.x);
    NSLog(@"fView y:%f; sView y:%f", self.fView.frame.origin.y, self.sView.frame.origin.y);
}

- (void) startAnimation {
    [self.fView setBounds:CGRectMake(60, 60, 100, 100)];
    
    NSLog(@"Bounds:");
    NSLog(@"fView x:%f; sView x:%f", self.fView.bounds.origin.x, self.sView.bounds.origin.x);
    NSLog(@"fView y:%f; sView y:%f", self.fView.bounds.origin.y, self.sView.bounds.origin.y);
    
    NSLog(@"frame:");
    NSLog(@"fView x:%f; sView x:%f", self.fView.frame.origin.x, self.sView.frame.origin.x);
    NSLog(@"fView y:%f; sView y:%f", self.fView.frame.origin.y, self.sView.frame.origin.y);
}

点击按钮我们发现,明明更改的是fView的bounds,为什么fView的位置没变,但是sView的位置向左上了呢?

其实setBounds中的(x,y)只改变自己的坐标系统,子View的bounds和frame并不会改变;

setBounds是修改自己坐标系的原点位置,进而影响到子View的显示位置;

bounds改变位置时,改变的是子视图的位置,自身没有影响,其实就是改变了自身的坐标系原点,默认原点在左上角。

因此执行完setBounds后,实际上是将当前fView的视图的原点移到了相对于原来原点的(60,60)位置,但是由于fView设定的frame是(100,100),因此它本身的frame不变,只是相当于移动了坐标系往左上了。又因为sView是fView的子视图,sView的frame是相对于fView的坐标系来设定位置的,因此,sView还是处于相对于fView的(0,0)位置,因此我们看上去sView的位置就像是随着fView的坐标系一起向左上移动了,但实际上sView的frame没有改变,打印出来还是(0,0)。

总结

frame: 描述视图在其父视图中的位置和大小,是"绝对"的。

bounds: 描述视图自身的内容区域和尺寸,是"相对"的。

相关推荐
ch_ziyuan1 小时前
2026新优化神马TV8.5影视点播系统保姆级搭建教程:三后台配置+反编译修改
android·ios·php
2601_955767422 小时前
观复盾 iPhone 17 Pro 护景贴深度评测:参数解析与实测避坑
人工智能·ios·ar·iphone·圆偏振光·磁控溅射
一拳一个娘娘腔4 小时前
【SRC漏洞挖掘系列】第11期:移动端安全(Android/iOS)—— APP 里的“猫腻”大起底
android·安全·ios
学习3人组4 小时前
IOS手机使用电脑代理 IP 作为网关/代理出口实现穿越上网
tcp/ip·ios·智能手机
2501_915106325 小时前
深入解析HTTPS抓包原理、中间人攻击及反抓包技术攻防
数据库·网络协议·ios·小程序·https·uni-app·iphone
ch_ziyuan5 小时前
跨平台APP封装分发系统搭建:iOS免签+安卓防报毒+IPA签名一体化
android·ios
游戏开发爱好者86 小时前
React Grab工具详解:AI助力Vue3、Svelte和Solid前端元素调试
android·ios·小程序·https·uni-app·iphone·webview
UXbot6 小时前
初创公司如何选择合适的UI工具支撑快速迭代产品?
人工智能·低代码·ios·交互·原型模式
CodeForCoffee6 小时前
iPhone照片导入Mac
macos·ios·iphone
Digitally6 小时前
如何将数据从传音(TECNO)手机迁移到 iPhone?
ios·智能手机·iphone