iOS: 具有隐藏视图的布局约束

iOS: layout constraint with hidden views

假设我有两个底部对齐的视图:

V:[Label1]-10-[Label2]-20-|

Label1Label2有10点间距,Label2和底部有20点间距

现在,在某些情况下,我需要隐藏 Label2,在这种情况下,我想要:

V:[Label1]-15-|

也就是说,Label2 被隐藏,Label1 到底部有 15 点间距。

我正在情节提要中设置它,我正在考虑使 15 点间距具有较低的优先级并根据需要隐藏 Label2,但它似乎不起作用。

实现此目标的最佳方法是什么?

谢谢!

通过保持您提到的低优先级约束,我找到的较短的解决方案是:

@IBOutlet weak var view2: UIView!
var constraints: [NSLayoutConstraint]? = nil

func foo() {
    if needsToHideView2 {
        constraints = view2.constraints
        NSLayoutConstraint.deactivate(view2.constraints)
    }
    if needsToShowView2 {
        NSLayoutConstraint.activate(constraints!)
    }
}

遗憾的是,隐藏视图只会影响 UIStackView 中的关联约束。这是因为 UIStackView 在隐藏视图时自动添加和删除约束。

解决这个问题的最佳方法是设置两组约束,adding/removing 每组都根据需要设置。我通常在创建这些约束 一个故事板,默认情况下不安装一组。然后,我为涉及的每个约束创建 IBOutlets,以便我可以轻松地在代码中引用它们:

if button.isHidden {
    self.view.addConstraint(self.hiddenConstraint)
    self.view.removeConstraint(self.visibleConstraint)      
} else {
    self.view.removeConstraint(self.hiddenConstraint)
    self.view.addConstraint(self.visibleConstraint)
}

I'm setting this up in storyboard

基本上,你不能。您将不得不使用代码来管理这些约束。当您隐藏 Label2 时,还要换出第一组约束并换入第二组约束。当您显示 Label2 时,也换出第二组约束并换入第一组。这是完全标准的程序。

事实上,我有一个示例项目可以有效地展示如何准确地执行您所描述的操作:

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch01p032constraintSwapping/ConstraintSwapping/ViewController.swift

如您所见,我们预先配置了视图 v2 存在和不存在的约束条件,并在我们删除或重新插入 v2 时交换它们。

如果在您的情况下合理,请使用 Label1 和 Label2 以及两个布局都处于活动状态来设置故事板。

对于 V:[Label1]-10-[Label2]-20-| 将 Label2 前导和尾随约束优先级设置为所需 (1000)

对于 V:[Label1]-15-| 将 Label1 尾随约束设置得较低(可能是 750)

然后,在适当的地方(viewDidLoad、layoutSubviews、updateConstraints 等),如果不需要 Label2,只需将其从其父视图中删除即可。