UIStackView 的子视图具有固有大小,但仍然忽略包含优先级的内容
Posted
技术标签:
【中文标题】UIStackView 的子视图具有固有大小,但仍然忽略包含优先级的内容【英文标题】:UIStackView's subviews have intrinsic size, yet still ignore content hugging priorities 【发布时间】:2020-07-09 22:40:16 【问题描述】:我正在尝试以编程方式创建一个具有填充分布的堆栈视图,允许我选择拉伸哪些子视图以填充额外空间,但到目前为止我似乎无法控制哪个视图正在扩展。
class ShelfVC: UIViewController
let shelfContentView = UIStackView()
override func viewDidLoad()
super.viewDidLoad()
view.addSubview(shelfContentView)
shelfContentView.translatesAutoresizingMaskIntoConstraints = false
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.widthAnchor.constraint(equalToConstant: 100).isActive = true
view1.backgroundColor = .systemRed
view1.setContentHuggingPriority(.defaultHigh, for: .horizontal)
let view2 = UIView()
shelfContentView.addArrangedSubview(view2)
view2.widthAnchor.constraint(equalToConstant: 100).isActive = true
view2.backgroundColor = .systemPurple
view2.setContentHuggingPriority(.defaultLow, for: .horizontal)
let view3 = UIView( )
shelfContentView.addArrangedSubview(view3)
view3.widthAnchor.constraint(equalToConstant: 100).isActive = true
view3.backgroundColor = .systemBlue
view3.setContentHuggingPriority(.defaultHigh, for: .horizontal)
我期待看到这个:
但是,相反,我看到了:
为什么蓝色视图的拥抱优先级高于紫色视图时会拉伸?
【问题讨论】:
【参考方案1】:Content Hugging Priority 与 Constraint Priority 不同,且 Constraints 不定义 Intrinsic Content Size。
内容拥抱(和内容压缩阻力)优先级基于内在内容大小。
您已经给每个视图一个 Width 约束,而您的堆栈视图正在使用它来开始 安排。然后它打破其中一个约束,因为它不能满足所有约束。
你有两个选择:
给约束不同的优先级 给视图一个固有内容大小并设置拥抱优先级这是第一个例子:
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
这是第二个例子:
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)
两者都产生相同的布局:
【讨论】:
【参考方案2】:UIStackView
根据内容压缩优先级使用.fill
收缩和扩展,如果排列的子视图没有填满堆栈视图。因此,请尝试将 setContentHuggingPriority
更改为 setContentCompressionResistancePriority
。
有关UIStackView.Distribution.fill
属性的更多信息,请参阅https://developer.apple.com/documentation/uikit/uistackview/distribution/fill。
【讨论】:
您的意思是尝试将setContentHuggingPriority
更改为setContentCompressionResistancePriority
?以上是关于UIStackView 的子视图具有固有大小,但仍然忽略包含优先级的内容的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Xcode 中调整 UIStackView 的子视图大小?
当 UIStackView 更改其排列的子视图时,UITableViewCell 不会调整大小