Objective-C 编写横竖屏适配UIView 按Label内容自动调整高度
问题根因
- 你采用了固定Frame硬编码的方式布局,所有控件的尺寸、位置都是基于视图初始化时的屏幕宽度计算,横竖屏切换后父视图尺寸发生变化,子控件的Frame不会自动同步更新,就会出现右侧超出屏幕、20pt边距失效的问题
- emptyTreeView高度固定写死为400,label2高度也固定为100,没有根据文本内容动态计算高度的逻辑,无法满足高度自适应的需求
推荐解决方案:使用AutoLayout实现自适应布局
AutoLayout是iOS官方提供的适配方案,能自动监听父视图尺寸变化,不需要手动计算横竖屏的Frame,同时可以完美实现内部控件自适应高度。
完整实现代码如下:
UIView *emptyTreeView = [[UIView alloc] init]; emptyTreeView.backgroundColor = [UIColor blueColor]; // 关闭自动转约束的开关 emptyTreeView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:emptyTreeView]; UILabel *label1 = [[UILabel alloc] init]; label1.backgroundColor = [UIColor redColor]; label1.textAlignment = NSTextAlignmentCenter; label1.textColor = [UIColor blackColor]; label1.font = [UIFont boldSystemFontOfSize:18]; label1.numberOfLines = 1; // 单行文本设为1即可 label1.text = @"The Page Cannot be displayed."; label1.translatesAutoresizingMaskIntoConstraints = NO; [emptyTreeView addSubview:label1]; UILabel *label2 = [[UILabel alloc] init]; label2.backgroundColor = [UIColor whiteColor]; label2.textAlignment = NSTextAlignmentCenter; label2.textColor = [UIColor grayColor]; label2.font = [UIFont systemFontOfSize:15]; label2.numberOfLines = 0; label2.text = @"Please use this feature or contact your internal contact person directly."; label2.translatesAutoresizingMaskIntoConstraints = NO; [emptyTreeView addSubview:label2]; // 激活约束 [NSLayoutConstraint activateConstraints:@[ // emptyTreeView约束:左右距父视图20,顶部距父视图20 [emptyTreeView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20], [emptyTreeView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-20], [emptyTreeView.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:20], // label1约束:顶部距emptyTreeView顶部30,左右距emptyTreeView左右30,高度固定30 [label1.topAnchor constraintEqualToAnchor:emptyTreeView.topAnchor constant:30], [label1.leadingAnchor constraintEqualToAnchor:emptyTreeView.leadingAnchor constant:30], [label1.trailingAnchor constraintEqualToAnchor:emptyTreeView.trailingAnchor constant:-30], [label1.heightAnchor constraintEqualToConstant:30], // label2约束:顶部距label1底部30,左右和label1对齐,底部距emptyTreeView底部30 [label2.topAnchor constraintEqualToAnchor:label1.bottomAnchor constant:30], [label2.leadingAnchor constraintEqualToAnchor:label1.leadingAnchor], [label2.trailingAnchor constraintEqualToAnchor:label1.trailingAnchor], [label2.bottomAnchor constraintEqualToAnchor:emptyTreeView.bottomAnchor constant:-30] ]];
如果你要坚持使用Frame布局,需要在viewWillLayoutSubviews方法中重新计算所有控件的Frame,同时提前计算文本的自适应高度,示例逻辑如下:
// 注意需要把emptyTreeView、label1、label2声明为当前类的成员变量 - (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; CGFloat viewWidth = self.view.frame.size.width; // 更新emptyTreeView的Frame CGFloat emptyTreeWidth = viewWidth - 40; emptyTreeView.frame = CGRectMake(20, 20, emptyTreeWidth, 0); // 更新label1 Frame CGFloat labelWidth = emptyTreeWidth - 60; label1.frame = CGRectMake(30, 30, labelWidth, 30); // 计算label2的自适应高度 CGSize label2Size = [label2.text boundingRectWithSize:CGSizeMake(labelWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:label2.font} context:nil].size; label2.frame = CGRectMake(30, 90, labelWidth, label2Size.height); // 更新emptyTreeView的总高度 CGFloat totalHeight = 30 + 30 + 30 + label2Size.height + 30; CGRect emptyFrame = emptyTreeView.frame; emptyFrame.size.height = totalHeight; emptyTreeView.frame = emptyFrame; }
内容的提问来源于stack exchange,提问作者iOSDude
相关产品推荐
相关产品推荐

