如何使自动布局约束依赖于多个其他锚?

Posted

技术标签:

【中文标题】如何使自动布局约束依赖于多个其他锚?【英文标题】:How to make auto-layout constraint dependent on multiple other anchors? 【发布时间】:2018-03-02 00:31:12 【问题描述】:

如何使用自动布局使视图的高度等于其他两个视图的高度之和?

例如:

viewA.heightAnchor.constraint(equalTo: ...),
viewB.heightAnchor.constraint(equalTo: ...),
viewC.heightAnchor.constraint(equalTo: viewA.heightAnchor + viewB.heightAnchor)

是否有不涉及设置常量值并在每次视图边界更改时重新计算它的解决方案?

【问题讨论】:

api中没有方法可以完成你想要的,唯一的解决办法就是处理equalToConstant 创建一个 LayoutGuide,它被限制在 ViewA 的顶部和 ViewB 的底部,然后将 ViewC 的高度锚限制到该布局指南(尚未测试) 【参考方案1】:

可以,但我认为只能借助一些辅助视图。请参阅我刚刚制作的这个示例游乐场,它实现了这一点:

import Foundation
import UIKit
import PlaygroundSupport

let vc = UIViewController()
vc.view = UIView()
vc.view.backgroundColor = .white

let viewA = UIView()
let viewB = UIView()
let viewC = UIView()

viewA.backgroundColor = .red
viewB.backgroundColor = .green
viewC.backgroundColor = .blue

viewA.translatesAutoresizingMaskIntoConstraints = false
viewB.translatesAutoresizingMaskIntoConstraints = false
viewC.translatesAutoresizingMaskIntoConstraints = false

vc.view.addSubview(viewA)
vc.view.addSubview(viewB)
vc.view.addSubview(viewC)

let helperViewA = UIView()
let helperViewB = UIView()

helperViewA.translatesAutoresizingMaskIntoConstraints = false
helperViewB.translatesAutoresizingMaskIntoConstraints = false

helperViewA.isHidden = true
helperViewB.isHidden = true

vc.view.addSubview(helperViewA)
vc.view.addSubview(helperViewB)

viewA.bottomAnchor.constraint(equalTo: vc.view.bottomAnchor).isActive = true
viewA.leadingAnchor.constraint(equalTo: vc.view.leadingAnchor).isActive = true
viewA.trailingAnchor.constraint(equalTo: viewB.leadingAnchor).isActive = true
viewA.heightAnchor.constraint(equalToConstant: 20.0).isActive = true

viewB.bottomAnchor.constraint(equalTo: vc.view.bottomAnchor).isActive = true
viewB.widthAnchor.constraint(equalTo: viewA.widthAnchor, multiplier: 1.0).isActive = true
viewB.trailingAnchor.constraint(equalTo: vc.view.trailingAnchor).isActive = true
viewB.heightAnchor.constraint(equalToConstant: 40.0).isActive = true

viewA.heightAnchor.constraint(equalTo: helperViewA.heightAnchor, multiplier: 1.0).isActive = true
viewB.heightAnchor.constraint(equalTo: helperViewB.heightAnchor, multiplier: 1.0).isActive = true

helperViewA.bottomAnchor.constraint(equalTo: helperViewB.topAnchor).isActive = true

viewC.widthAnchor.constraint(equalToConstant: 100).isActive = true
viewC.topAnchor.constraint(equalTo: helperViewA.topAnchor).isActive = true
viewC.bottomAnchor.constraint(equalTo: helperViewB.bottomAnchor).isActive = true


helperViewA.leadingAnchor.constraint(equalTo: viewC.leadingAnchor).isActive = true
helperViewA.trailingAnchor.constraint(equalTo: viewC.trailingAnchor).isActive = true
helperViewB.leadingAnchor.constraint(equalTo: viewC.leadingAnchor).isActive = true
helperViewB.trailingAnchor.constraint(equalTo: viewC.trailingAnchor).isActive = true

viewC.centerXAnchor.constraint(equalTo: vc.view.centerXAnchor).isActive = true
viewC.centerYAnchor.constraint(equalTo: vc.view.centerYAnchor).isActive = true

vc.view.frame.size = CGSize(width: 375, height: 667)
PlaygroundPage.current.liveView = vc.view

这个想法是你有两个互相垂直堆叠的辅助视图,由顶部的bottomAnchor 和底部的topAnchor 连接。然后,您将每个辅助视图的高度设置为等于您的viewAviewB 高度。然后,您的viewC 可以附加到顶视图的topAnchor 和底视图的bottomAnchor,结果viewC 的高度是viewA 的高度加上viewB 的高度。

【讨论】:

用父视图解决它不是一个解决方案,他需要任何2个单独的视图 @Sh_Khan 我不知道你所说的“用父视图解决它”是什么意思。 我的意思是你解决它假设两个视图都在彼此的正下方,这可能并非总是如此,如果它们之间有任何空白空间,它将被视为一个加空间 > 的总和viewA 和 ViewB 高度 helper 视图在彼此的上方和下方,是的,但不是 OP 问题中的视图(viewA 和 viewB)。 @TylerTheCompiler 很好的解决方法,也是我能想到的唯一解决方法。在 Apple 将此添加到他们的 API 之前,实际上可以为 NSLayoutAnchor 编写一个扩展并使用您的解决方法。

以上是关于如何使自动布局约束依赖于多个其他锚?的主要内容,如果未能解决你的问题,请参考以下文章

具有锚样式自动布局约束的 UIButtons 未显示

你如何自动布局约束按钮内的通知标签?

斯威夫特:我无法使自动布局约束适用于我的 UIScrollView

如何使用自动布局使超级视图适合最大的内在大小子视图

自动布局约束未正确放置容器视图

iOS - 具有自动布局的依赖约束控制台输出