Content Hugging Priority is not the same as Constraint Priority, and Constraints do not define Intrinsic Content Size.
Content Hugging (and Content Compression Resistance) Priority is based on Intrinsic content size.
You've given each view a Width constraint, and your stack view is using that to begin the arrangement. It then breaks one of the constraints because it cannot satisfy all of them.
You have two options:
- give the constraints different priorities
- give the views an intrinsic content size and set Hugging priority
Here is the first example:
class ConstraintHuggingShelfVC: UIViewController {
let shelfContentView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(shelfContentView)
shelfContentView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
shelfContentView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0.0),
shelfContentView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0),
shelfContentView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0),
shelfContentView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0),
])
//shelfContentView.layoutEqualTo(view: view)
shelfContentView.spacing = 16
shelfContentView.isLayoutMarginsRelativeArrangement = true
let shelfMargin = CGFloat(16)
shelfContentView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: shelfMargin, leading: shelfMargin, bottom: shelfMargin, trailing: shelfMargin)
createTestBlocks()
}
func createTestBlocks() {
let view1 = UIView()
shelfContentView.addArrangedSubview(view1)
view1.backgroundColor = .systemRed
let wc1 = view1.widthAnchor.constraint(equalToConstant: 100)
wc1.isActive = true
wc1.priority = .defaultHigh
let view2 = UIView()
shelfContentView.addArrangedSubview(view2)
view2.backgroundColor = .systemPurple
let wc2 = view2.widthAnchor.constraint(equalToConstant: 100)
wc2.isActive = true
wc2.priority = .defaultLow
let view3 = UIView( )
shelfContentView.addArrangedSubview(view3)
view3.backgroundColor = .systemBlue
let wc3 = view3.widthAnchor.constraint(equalToConstant: 100)
wc3.isActive = true
wc3.priority = .defaultHigh
}
}
and here's the second example:
class IntrinsicView: UIView {
var myIntrinsicSize: CGSize = .zero
override var intrinsicContentSize: CGSize {
return myIntrinsicSize
}
}
class IntrisicSizeShelfVC: UIViewController {
let shelfContentView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(shelfContentView)
shelfContentView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
shelfContentView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0.0),
shelfContentView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0),
shelfContentView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0),
shelfContentView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0),
])
// shelfContentView.layoutEqualTo(view: view)
shelfContentView.spacing = 16
shelfContentView.isLayoutMarginsRelativeArrangement = true
let shelfMargin = CGFloat(16)
shelfContentView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: shelfMargin, leading: shelfMargin, bottom: shelfMargin, trailing: shelfMargin)
createTestBlocks()
}
func createTestBlocks() {
let view1 = IntrinsicView()
shelfContentView.addArrangedSubview(view1)
view1.backgroundColor = .systemRed
view1.myIntrinsicSize = CGSize(width: 100, height: 0)
view1.setContentHuggingPriority(.defaultHigh, for: .horizontal)
let view2 = IntrinsicView()
shelfContentView.addArrangedSubview(view2)
view2.backgroundColor = .systemPurple
view2.myIntrinsicSize = CGSize(width: 100, height: 0)
view2.setContentHuggingPriority(.defaultLow, for: .horizontal)
let view3 = IntrinsicView( )
shelfContentView.addArrangedSubview(view3)
view3.backgroundColor = .systemBlue
view3.myIntrinsicSize = CGSize(width: 100, height: 0)
view3.setContentHuggingPriority(.defaultHigh, for: .horizontal)
}
}
Both produce the identical layout:
