在运行时以编程方式激活约束

Posted

技术标签:

【中文标题】在运行时以编程方式激活约束【英文标题】:activating constraints programmatically at runtime 【发布时间】:2017-11-01 06:26:49 【问题描述】:

我想在运行时使用约束以编程方式更改视图的位置 我有以下观点安排

 |
viewA
 |
viewB
 |
viewC

假设我将viewAtopAnchor 约束设置为父视图边缘的顶部,viewBtopAnchor 设置为viewA 等等viewC

我想在运行时更改这些视图在某些操作上的位置

 |
viewA
 |
viewC
 |
viewB

我为viewB 存储了两个不同的约束,一个在viewA 的顶部,另一个在viewC 的顶部

viewBTopConstraints = viewB.topAnchor.constraint(equalTo: viewA.bottomAnchor, constant: TOP_SPACE)

newViewBTopConstraints = viewB.topAnchor.constraint(equalTo: viewC.bottomAnchor, constant: TOP_SPACE)

在我的切换操作方法中,我做了类似的事情

viewBTopConstraints?.isActive = false
newViewBTopConstraints?.isActive = true

这在第一次运行时有效,但第二次失败,在视图调试器中进一步调试时我发现它会创建重复的约束而不是更改原始约束。

【问题讨论】:

你应该只在第一次之后修改isActive 有没有办法实现这种行为?我想要的只是根据某些操作切换这些视图的位置,因为我已经使用约束以编程方式创建了我的视图,所以我无法弄清楚。 【参考方案1】:

您的要求听起来类似于我有一些基于横向或纵向更改的限制的应用程序。在那里我设置了组约束:

那些总是isActive = true 肖像中的isActive = true 那些isActive = true 在横向

诀窍是将后两者放入数组中,并在正确的时间激活/停用正确的数组。这是我的意思的sn-p:

var p = [NSLayoutConstraint]()
var l = [NSLayoutConstraint]()


////// portrait layout....

// pin info button above imageLayout, right justified

p.append(info.topAnchor.constraint(equalTo: margins.topAnchor, constant: 20.0))
p.append(info.trailingAnchor.constraint(equalTo: margins.trailingAnchor))


////// landscape layout....

// pin info button above buttons, right justified

l.append(info.topAnchor.constraint(equalTo: margins.topAnchor, constant: 20.0))
l.append(info.trailingAnchor.constraint(equalTo: margins.trailingAnchor))

请注意,我没有设置任何isActive = true。我只是根据需要将东西附加到两个数组中。现在,在 viewWillLayoutSubviews() - 根据您的需要,viewDidLayoutSubviews() 可能是更好的替代 - 您*激活/停用正确的数组:

NSLayoutConstraint.deactivate(l)
NSLayoutConstraint.deactivate(p)
if self.bounds.width > self.bounds.height 
    NSLayoutConstraint.activate(l)
 else 
    NSLayoutConstraint.activate(p)

我发现使用单独的约束,设置isActive,会大大增加发生冲突的风险。

【讨论】:

以上是关于在运行时以编程方式激活约束的主要内容,如果未能解决你的问题,请参考以下文章

出现键盘时以编程方式更新约束

无法在运行时以编程方式影响闪烁控制

在使用像 EF 这样的 ORM 时,是不是可以在运行时以编程方式创建新表?

在运行时以编程方式更改 SVG 类

我可以在应用程序运行时以编程方式翻转 Info.plist 值吗?

在需要时以编程方式添加滚动