三个UIView等宽并排占满屏,移除一个后剩余两视图占满屏实现方案
解决动态调整UIView宽度的几种方案
这问题我之前做类似自适应布局时刚好碰到过,给你几个实用的方案,从最省心的开始说:
方案一:用UIStackView(最推荐)
这绝对是苹果官方最推荐的实现方式,完全不用手动管理约束变更,StackView会帮你搞定一切。
步骤很简单:
- 把三个UIView放进一个水平方向的UIStackView里
- 给StackView设置和父视图的约束:
leading、trailing、top(或你需要的顶部约束)、bottom(或底部约束),让它完全占满屏幕宽度方向的空间 - 设置StackView的两个关键属性:
distribution设为.fillEqually:让所有子视图均分可用空间spacing设为0:确保子视图之间没有间隙
不管是用代码还是Storyboard/XIB都很方便:
代码实现示例:
// 创建三个子视图(假设你已经初始化了view1、view2、view3) let stackView = UIStackView(arrangedSubviews: [view1, view2, view3]) stackView.axis = .horizontal stackView.distribution = .fillEqually stackView.spacing = 0 // 将StackView添加到父视图并设置约束 stackView.translatesAutoresizingMaskIntoConstraints = false parentView.addSubview(stackView) NSLayoutConstraint.activate([ stackView.leadingAnchor.constraint(equalTo: parentView.leadingAnchor), stackView.trailingAnchor.constraint(equalTo: parentView.trailingAnchor), stackView.topAnchor.constraint(equalTo: parentView.topAnchor), stackView.bottomAnchor.constraint(equalTo: parentView.bottomAnchor) ])
移除视图时的操作:
只需要两步,StackView会自动调整剩余视图的宽度:
// 先从StackView的排列列表中移除 stackView.removeArrangedSubview(viewToRemove) // 再从父视图中移除 viewToRemove.removeFromSuperview() // 如果需要动画效果,包在动画块里就行 UIView.animate(withDuration: 0.3) { self.parentView.layoutIfNeeded() }
方案二:手动管理Auto Layout约束(适合特殊场景)
如果你因为某些原因不想用StackView,那可以手动维护宽度约束的乘数。
核心思路是:
- 初始化时给每个视图的宽度约束设置为父视图宽度的
1/3 - 移除一个视图后,把剩余两个视图的宽度约束乘数改成
1/2
代码实现示例:
// 先保存每个视图的宽度约束引用,方便后续修改 private var view1WidthConstraint: NSLayoutConstraint! private var view2WidthConstraint: NSLayoutConstraint! private var view3WidthConstraint: NSLayoutConstraint! // 初始化约束 func setupConstraints() { // 先给三个视图设置水平排列的约束(view1贴左,view2跟在view1后面,view3贴右) NSLayoutConstraint.activate([ view1.leadingAnchor.constraint(equalTo: parentView.leadingAnchor), view2.leadingAnchor.constraint(equalTo: view1.trailingAnchor), view3.trailingAnchor.constraint(equalTo: parentView.trailingAnchor), // 垂直方向的约束根据你的需求设置,比如上下对齐父视图 view1.topAnchor.constraint(equalTo: parentView.topAnchor), view1.bottomAnchor.constraint(equalTo: parentView.bottomAnchor), view2.topAnchor.constraint(equalTo: parentView.topAnchor), view2.bottomAnchor.constraint(equalTo: parentView.bottomAnchor), view3.topAnchor.constraint(equalTo: parentView.topAnchor), view3.bottomAnchor.constraint(equalTo: parentView.bottomAnchor) ]) // 设置宽度约束,乘数为1/3 view1WidthConstraint = view1.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 1/3) view2WidthConstraint = view2.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 1/3) view3WidthConstraint = view3.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 1/3) NSLayoutConstraint.activate([view1WidthConstraint, view2WidthConstraint, view3WidthConstraint]) } // 移除视图的方法 func removeView(_ viewToRemove: UIView) { viewToRemove.removeFromSuperview() // 根据移除的视图,更新剩余视图的宽度约束 switch viewToRemove { case view1: view2WidthConstraint.isActive = false view3WidthConstraint.isActive = false view2WidthConstraint = view2.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 1/2) view3WidthConstraint = view3.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 1/2) case view2: view1WidthConstraint.isActive = false view3WidthConstraint.isActive = false view1WidthConstraint = view1.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 1/2) view3WidthConstraint = view3.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 1/2) case view3: view1WidthConstraint.isActive = false view2WidthConstraint.isActive = false view1WidthConstraint = view1.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 1/2) view2WidthConstraint = view2.widthAnchor.constraint(equalTo: parentView.widthAnchor, multiplier: 1/2) default: break } // 激活新的约束并更新布局 NSLayoutConstraint.activate([view1WidthConstraint, view2WidthConstraint, view3WidthConstraint].compactMap { $0 }) UIView.animate(withDuration: 0.3) { self.parentView.layoutIfNeeded() } }
总结
优先选择UIStackView方案,它的代码量少、逻辑简单,而且苹果已经帮我们处理了所有布局变更的细节,不容易出错。手动约束的方案适合一些特殊的定制化场景,但需要额外维护约束的状态,相对繁琐。
内容的提问来源于stack exchange,提问作者Videh Jaiswal
相关产品推荐
相关产品推荐

