基于子视图自动设置容器视图的高度
Auto set height of container view based on subviews
我知道这个问题已经被问过很多次了,但我似乎无法弄清这个问题的真相。
使用自动布局,我想根据其子视图自动设置容器 UIView 的高度。我已经研究过使用 sizeToFit
和其他各种方法来总结我的子视图的高度,但是从我读到的内容来看,由于子视图 "intrinsic"内容大小。
以下是我遇到的情况的简化案例。非常感谢任何指导!
概览:
- 创建容器 UIView,固定到 superview 的左右两侧,没有明确的高度,将其 centerY 与其 superview centerY 对齐
- 创建一个 300 宽 x 100 高的 UIView,将其作为子视图添加到容器视图,将其 centerX 与容器视图的 centerX 对齐,固定到容器视图的顶部边缘
- 重复步骤 #2,除了这次将其顶部固定到 #2 的底部边缘
- 容器视图的预期高度为 200,但它的高度实际上仍为 0(因此 centerY 对齐已关闭)
代码:
class ViewController: UIViewController {
let redView = RedView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(redView)
view.setNeedsUpdateConstraints()
}
}
class RedView: UIView {
let greenView = GreenView()
let blueView = BlueView()
init() {
super.init(frame: CGRect.zero)
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = UIColor.red()
addSubview(greenView)
addSubview(blueView)
setNeedsUpdateConstraints()
}
override func updateConstraints() {
super.updateConstraints()
NSLayoutConstraint(item: greenView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: blueView, attribute: .top, relatedBy: .equal, toItem: greenView, attribute: .bottom, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal, toItem: superview, attribute: .left, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: self, attribute: .right, relatedBy: .equal, toItem: superview, attribute: .right, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: superview, attribute: .centerY, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200).isActive = true
}
}
class GreenView: UIView {
init() {
super.init(frame: CGRect.zero)
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = UIColor.green()
}
override func updateConstraints() {
super.updateConstraints()
NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 300).isActive = true
NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100).isActive = true
NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: superview, attribute: .centerX, multiplier: 1, constant: 0).isActive = true
}
}
class BlueView: UIView {
init() {
super.init(frame: CGRect.zero)
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = UIColor.blue()
}
override func updateConstraints() {
super.updateConstraints()
NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 300).isActive = true
NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100).isActive = true
NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: superview, attribute: .centerX, multiplier: 1, constant: 0).isActive = true
}
}
您需要将 blueView 的底部固定到 redView 的底部,只需将此行添加到 redView 的 updateConstraints
:
NSLayoutConstraint(item: blueView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0).active = true
我知道这个问题已经被问过很多次了,但我似乎无法弄清这个问题的真相。
使用自动布局,我想根据其子视图自动设置容器 UIView 的高度。我已经研究过使用 sizeToFit
和其他各种方法来总结我的子视图的高度,但是从我读到的内容来看,由于子视图 "intrinsic"内容大小。
以下是我遇到的情况的简化案例。非常感谢任何指导!
概览:
- 创建容器 UIView,固定到 superview 的左右两侧,没有明确的高度,将其 centerY 与其 superview centerY 对齐
- 创建一个 300 宽 x 100 高的 UIView,将其作为子视图添加到容器视图,将其 centerX 与容器视图的 centerX 对齐,固定到容器视图的顶部边缘
- 重复步骤 #2,除了这次将其顶部固定到 #2 的底部边缘
- 容器视图的预期高度为 200,但它的高度实际上仍为 0(因此 centerY 对齐已关闭)
代码:
class ViewController: UIViewController {
let redView = RedView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(redView)
view.setNeedsUpdateConstraints()
}
}
class RedView: UIView {
let greenView = GreenView()
let blueView = BlueView()
init() {
super.init(frame: CGRect.zero)
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = UIColor.red()
addSubview(greenView)
addSubview(blueView)
setNeedsUpdateConstraints()
}
override func updateConstraints() {
super.updateConstraints()
NSLayoutConstraint(item: greenView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: blueView, attribute: .top, relatedBy: .equal, toItem: greenView, attribute: .bottom, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal, toItem: superview, attribute: .left, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: self, attribute: .right, relatedBy: .equal, toItem: superview, attribute: .right, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: superview, attribute: .centerY, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200).isActive = true
}
}
class GreenView: UIView {
init() {
super.init(frame: CGRect.zero)
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = UIColor.green()
}
override func updateConstraints() {
super.updateConstraints()
NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 300).isActive = true
NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100).isActive = true
NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: superview, attribute: .centerX, multiplier: 1, constant: 0).isActive = true
}
}
class BlueView: UIView {
init() {
super.init(frame: CGRect.zero)
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = UIColor.blue()
}
override func updateConstraints() {
super.updateConstraints()
NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 300).isActive = true
NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100).isActive = true
NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: superview, attribute: .centerX, multiplier: 1, constant: 0).isActive = true
}
}
您需要将 blueView 的底部固定到 redView 的底部,只需将此行添加到 redView 的 updateConstraints
:
NSLayoutConstraint(item: blueView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0).active = true