简体   繁体   中英

How to make auto-layout constraint dependent on multiple other anchors?

How can auto-layout be used to make a view's height equal to the sum of two other view's heights?

For example:

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

Is there a solution that does not involve setting a constant value and recalculating it on every view bounds change?

You can , but only with the help of some helper views, I think. See this example playground I just now cooked up that achieves this:

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

The idea is that you have two helper views stacked vertically on each other, connected by the top one's bottomAnchor and the bottom one's topAnchor . You then set each of these helper views' heights to be equal to your viewA and viewB heights. Then, your viewC can be attached to the top view's topAnchor and the bottom view's bottomAnchor , which gives the result of viewC being the height of viewA 's height plus viewB 's height.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM