如何让UIKit视图自动压缩以适配不同屏幕方向尺寸
问题核心原因
你当前使用的heightAnchor.constraint(equalToConstant: 88)是优先级为UILayoutPriority.required(1000)的强制约束,AutoLayout必须严格满足该约束值,因此横屏高度不足时不会自动压缩,只会出现约束冲突、布局溢出。之前调整布局优先级未生效,是因为仅修改固定高度约束的优先级时,系统没有可参考的边界约束来判断压缩规则,无法自动计算适配后的高度。
自动适配实现方案
无需编写横竖屏切换的判断逻辑,仅通过调整约束组合和优先级,即可实现空间充足时保持88pt高度、空间不足时5个视图等比压缩不溢出屏幕的效果:
- 把每个视图的固定高度约束,替换为高度不大于88pt的最高可选优先级约束(
UILayoutPriority.defaultHigh(999)) - 保留5个视图高度相等的关联约束,保证压缩时所有视图高度同步变化
- 给最后一个视图增加底部不超出安全区的强制约束(优先级1000),作为布局的下边界
- 可选:增加最小高度强制约束,避免横屏时视图被压缩到过小影响内容显示
实现代码如下:
// 创建第一个视图的最大高度约束,优先级设为非必须的高优先级 let firstViewMaxHeight = firstView.heightAnchor.constraint(lessThanOrEqualToConstant: 88) firstViewMaxHeight.priority = .defaultHigh // 可选:设置最小高度,避免视图被过度压缩 let firstViewMinHeight = firstView.heightAnchor.constraint(greaterThanOrEqualToConstant: 44) NSLayoutConstraint.activate([ // 第一个视图约束 firstView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), firstView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor), firstView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor), firstViewMaxHeight, firstViewMinHeight, // 第二个视图约束 secondView.topAnchor.constraint(equalTo: firstView.bottomAnchor), secondView.leftAnchor.constraint(equalTo: firstView.leftAnchor), secondView.rightAnchor.constraint(equalTo: firstView.rightAnchor), secondView.heightAnchor.constraint(equalTo: firstView.heightAnchor), // 第三个视图约束 thirdView.topAnchor.constraint(equalTo: secondView.bottomAnchor), thirdView.leftAnchor.constraint(equalTo: firstView.leftAnchor), thirdView.rightAnchor.constraint(equalTo: firstView.rightAnchor), thirdView.heightAnchor.constraint(equalTo: firstView.heightAnchor), // 第四个视图约束 fourthView.topAnchor.constraint(equalTo: thirdView.bottomAnchor), fourthView.leftAnchor.constraint(equalTo: firstView.leftAnchor), fourthView.rightAnchor.constraint(equalTo: firstView.rightAnchor), fourthView.heightAnchor.constraint(equalTo: firstView.heightAnchor), // 第五个视图约束:底部不能超出安全区,为必须满足的强制约束 fifthView.topAnchor.constraint(equalTo: fourthView.bottomAnchor), fifthView.leftAnchor.constraint(equalTo: firstView.leftAnchor), fifthView.rightAnchor.constraint(equalTo: firstView.rightAnchor), fifthView.heightAnchor.constraint(equalTo: firstView.heightAnchor), fifthView.bottomAnchor.constraint(lessThanOrEqualTo: view.safeAreaLayoutGuide.bottomAnchor) ])
适配逻辑说明
- 竖屏状态下,安全区可用高度大于5*88=440pt,强制约束(不超出底部、最小高度)可轻松满足,系统会优先满足高优先级的最大高度约束,所有视图保持88pt高度
- 横屏状态下,安全区可用高度小于440pt,强制约束优先级更高,系统会自动等比降低每个视图的高度,直到5个视图总高度刚好适配屏幕,不会出现溢出
- 如果需要竖屏时5个视图刚好撑满整个安全区,只需要把最后一个视图的底部约束从
lessThanOrEqualTo改成equalTo即可
最终实现效果:

内容的提问来源于stack exchange,提问作者Alyafai
相关产品推荐
相关产品推荐

