I have set up constraints to allow UIView cv1
to change height dynamically according to screen size, with the heights of cv2
and cv3
fixed.
For some reason, when I run this as shown, cv3
's view height becomes 172.
Using the original cv3.heightAnchor.constraint(equalToConstant: cv3Height)
in one or the other or both, I run into the same problem as here (which worked perfectly for cv2
), with the added effect that where I replace it with h3,
(narrow or wide) the view jumps to 172 only in that orientation but also gives me the conflicting constraints message.
I deleted ALL other constraints without luck.
Is this another bug? If so, is there a workaround?
Here is a minimized function, the entire function below:
func setConstraints() {
cv3.translatesAutoresizingMaskIntoConstraints = false
let g = view.safeAreaLayoutGuide
let cv3Height: CGFloat = 125
let h3 = cv3.heightAnchor.constraint(equalToConstant: cv3Height)
h3.priority = .defaultHigh
narrowConstraints = [
// set cv3 height
//cv3.heightAnchor.constraint(equalToConstant: cv3Height),
h3,
// lock left, right and bottom to safe area
cv3.leadingAnchor.constraint(equalTo: g.leadingAnchor),
cv3(equalTo: g.trailingAnchor),
cv3(equalTo: g.bottomAnchor),
]
wideConstraints = [
// set cv3 height
//cv3.heightAnchor.constraint(equalToConstant: cv3Height),
h3,
// lock bottom and right side of cv3 to safe area
cv3(equalTo: g.trailingAnchor),
cv3(equalTo: g.bottomAnchor),
// make them all equal widths
cv2.widthAnchor.constraint(equalTo: cv1.widthAnchor),
cv3.widthAnchor.constraint(equalTo: cv2.widthAnchor),
]
// activate the commonConstraints
NSLayoutConstraint.activate(commonConstraints)
if view.frame.width > view.frame.height {
// wider than tall, so "landscape"
NSLayoutConstraint.deactivate(narrowConstraints)
NSLayoutConstraint.activate(wideConstraints)
} else {
// taller than wide
NSLayoutConstraint.deactivate(wideConstraints)
NSLayoutConstraint.activate(narrowConstraints)
}
}
Here is the entire function:
func setConstraints() {
cv1.translatesAutoresizingMaskIntoConstraints = false
cv2.translatesAutoresizingMaskIntoConstraints = false
cv3.translatesAutoresizingMaskIntoConstraints = false
let g = view.safeAreaLayoutGuide
let cv2Height: CGFloat = 190
let h2 = cv2.heightAnchor.constraint(equalToConstant: cv2Height)
h2.priority = .defaultHigh
let cv3Height: CGFloat = 125
let h3 = cv3.heightAnchor.constraint(equalToConstant: cv3Height)
h3.priority = .defaultHigh
narrowConstraints = [
// lock top, left and right to safe area
cv1.topAnchor.constraint(equalTo: g.topAnchor),
cv1.leadingAnchor.constraint(equalTo: g.leadingAnchor),
cv1.trailingAnchor.constraint(equalTo: g.trailingAnchor),
// set cv2 height
//cv2.heightAnchor.constraint(equalToConstant: cv2Height),
h2,
// lock left and right to safe area
cv2.leadingAnchor.constraint(equalTo: g.leadingAnchor),
cv2.trailingAnchor.constraint(equalTo: g.trailingAnchor),
// lock top of cv2 to bottom of cv1
cv2.topAnchor.constraint(equalTo: cv1.bottomAnchor),
// lock bottom of cv2 to top of cv3
cv2.bottomAnchor.constraint(equalTo: cv3.topAnchor),
// set cv3 height
//cv3.heightAnchor.constraint(equalToConstant: cv3Height),
h3,
// lock left, right and bottom to safe area
cv3.leadingAnchor.constraint(equalTo: g.leadingAnchor),
cv3(equalTo: g.trailingAnchor),
cv3(equalTo: g.bottomAnchor),
]
wideConstraints = [
// lock top, bottom, and left to safe area
cv1.topAnchor.constraint(equalTo: g.topAnchor),
cv1.bottomAnchor.constraint(equalTo: g.bottomAnchor),
cv1.leadingAnchor.constraint(equalTo: g.leadingAnchor),
// lock right side of cv1 to left side of cv2
cv1.trailingAnchor.constraint(equalTo: cv2.leadingAnchor),
// lock right side of cv2 to safe area
cv2.trailingAnchor.constraint(equalTo: g.trailingAnchor),
// lock top of cv2 to safe area
cv2.topAnchor.constraint(equalTo: g.topAnchor),
// lock bottom of cv2 to top of cv3
cv2.bottomAnchor.constraint(equalTo: cv3.topAnchor),
// set cv3 height
//cv3.heightAnchor.constraint(equalToConstant: cv3Height),
h3,
// lock bottom and right side of cv3 to safe area
cv3(equalTo: g.trailingAnchor),
cv3(equalTo: g.bottomAnchor),
// make them all equal widths
cv2.widthAnchor.constraint(equalTo: cv1.widthAnchor),
cv3.widthAnchor.constraint(equalTo: cv2.widthAnchor),
]
// activate the commonConstraints
NSLayoutConstraint.activate(commonConstraints)
if view.frame.width > view.frame.height {
// wider than tall, so "landscape"
NSLayoutConstraint.deactivate(narrowConstraints)
NSLayoutConstraint.activate(wideConstraints)
} else {
// taller than wide
NSLayoutConstraint.deactivate(wideConstraints)
NSLayoutConstraint.activate(narrowConstraints)
}
}
I looks like the issue is the every time the function is called, you're creating new constraints but not deactivating the old constraints from the previous time it was run.
For example, the first time it's called it'll create a set of wide and narrow constraints and activate the wide set. The next time it's called it'll create a new set of wide and narrow constraints and activate the narrow constraints from the second set without deactivating the wide constraints from the first set. Your call to deactivate it being called on the second set which would have on effect.
I'd guess the conflicting constraints message is showing the constraints from the first set that haven't been deactivated.
What I would do is split your function into two separate functions.
Make a setupConstraints
function that only creates the arrays of constraints and activates just the commonConstraints
. The important part would be to make sure this function is called only once.
Make a activateConstraintsForOrientation
function that only contains the if statement at the bottom of your function. You'd then call this function anytime you think the orientation has changed.
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.