UIStackView无法满足的自动布局约束

时间:2018-12-05 16:48:05

标签: ios autolayout uikit nslayoutconstraint uistackview

我在情节提要中定义了一个UIStackView,第一个按钮的高度设置为70,其他按钮的高度设置为45。我收到此自动布局错误:

 [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. 
Try this: 
    (1) look at each constraint and try to figure out which you don't expect; 
    (2) find the code that added the unwanted constraint or constraints and fix it. 
 (
"<NSLayoutConstraint:0x280f614f0 UIButton:0x10641a120.height == 45   (active)>",
"<NSLayoutConstraint:0x280f60e60 UIButton:0x106418f80.height == 70   (active)>",
"<NSLayoutConstraint:0x280f604b0 'UISV-alignment' UIButton:0x10641a120.bottom == UIButton:0x106418f80.bottom   (active)>",
"<NSLayoutConstraint:0x280f63cf0 'UISV-alignment' UIButton:0x10641a120.top == UIButton:0x106418f80.top   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x280f60e60 UIButton:0x106418f80.height == 70   (active)>

我了解UIStackView无法接受不同高度的UIButton,这是正确的吗?让UIStackView接受其元素的不同高度或宽度的方法是什么?

2 个答案:

答案 0 :(得分:1)

您的Stack View约束中的问题导致了此问题。

这是有效的布局:

enter image description here

具有“堆栈视图”属性:

enter image description here

通过代码添加第三个按钮之前的结果:

enter image description here

然后结果 通过代码添加第三个按钮(高度限制为60):

enter image description here

没有自动布局警告或错误。

代码(连接到按钮1),添加/删除Button 3作为堆栈视图的排列子视图:

class TestViewController: UIViewController {

    @IBOutlet var theStackView: UIStackView!

    var thirdButton: UIButton = {
        let b = UIButton()
        b.translatesAutoresizingMaskIntoConstraints = false
        b.setTitle("Button 3", for: .normal)
        b.backgroundColor = .red
        return b
    }()

    @IBAction func doAddThird(_ sender: Any) {

        if theStackView.arrangedSubviews.count == 2 {

            theStackView.addArrangedSubview(thirdButton)

        } else {

            if let v = theStackView.arrangedSubviews.last {
                v.removeFromSuperview()
            }

        }

    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // finish initializing the third button
        if let v = theStackView.arrangedSubviews.first as? UIButton {
            thirdButton.titleLabel?.font = v.titleLabel?.font
        }

        NSLayoutConstraint.activate([
            thirdButton.heightAnchor.constraint(equalToConstant: 60),
            ])

    }   
}

答案 1 :(得分:0)

如果没有给它高度和宽度约束,则Stackview将采用其组件的尺寸。似乎您是在告诉您的stackView是特定的高度(要么是因为您有一个高度约束,要么是两个Y位置约束暗示着一个高度)。除非这两个值完全相同,否则您既不能告诉stackView具有高度,又不能告诉其所有splittedSubviews具有高度。因此,例如,如果您告诉堆栈高度为150,而按钮分别为45和70,那么内容优先级最低的按钮将丢失并被扩展以占用堆栈视图所需的额外35点空间高150点。

快速解决方案:

  1. 删除堆栈视图上的hieght约束;现在将达到其元素的最高值之​​和。
  2. 将一个空白的UIView添加到堆栈中,并使其内容包含1,它将占用任何额外的空间(仅当您的堆栈大于其元素时才有效;如果堆栈太小,则需要减小堆栈的大小改为安排了Subviews。)