Reputation: 4413
Using Xcode 10, iOS 11.4+, Swift 4
I have a series of UIViewControllers that I am navigating through, each of which is being placed into a ContainerView.
Based on which VC is pushed, I am hiding/showing the Top or Bottom views (shown in gray) in the Main Controller while the ContainerView is always in the middle (light blue).
What I would like to do is set the constraints so that the ContainerView is appropriately sized when the Top or Bottom views are shown/hidden.
For example, when the "Main Menu" is shown, the ContainerView should fill the entire Main Container view (Top and Bottom views will be hidden)
When "Item1" is shown, the Top view will be shown and the Bottom view hidden. Therefore, ContainerView should fill the Main Container view left, right, and bottom, but the ContainerView Top should be constrained to the Top view bottom.
When "Item5" is shown, the Top and Bottom views will also be shown. Therefore, ContainerView should fill Main Container view left, right, and be constrained to the Top view bottom, and the Bottom view top (as shown in the Main Container)
I've tried using code like this to fill the entire Main view:
NSLayoutConstraint.activate([
ContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0),
ContainerView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0),
ContainerView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0),
ContainerView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0)
])
However, the ContainerView never changes, and Xcode gives me a lot of warnings like:
[LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want.
Here's another screenshot from the Storyboard:
Here's a link to download my sample project: https://gitlab.com/whoit/containerviews
How can I correctly modify the constraints to accomplish this?
Upvotes: 2
Views: 1643
Reputation: 6693
1) You're adding new constraints all the time, as this lines create a new constraints, each time they're getting called:
ContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0)
2) In the beginning, the MainContainerView
is not constraint at all
I would suggest following:
constant
s of those to 0
(when hiding them)alpha
as well, and then add the height constant to the completion block.Note:
Hidden views (alpha = 0
or isHidden = true
) are still taken into account for layouting. That means, your constraints are still valid, when the views are hidden. But to make them look like hidden for the layouting as well, you'll then have to set theirs height constant
s to 0
.
@objc func hideControlViews(_ notification: Notification){
let userInfo = notification.userInfo! as! [String : Bool]
//print("Got top view notification: \(String(describing: userInfo["hide"]))")
if (userInfo["hidetop"]!) {
self.topViewHeightConstraint.constant = 0
} else {
self.topViewHeightConstraint.constant = 64
}
if (userInfo["hidebottom"]!) {
self.bottomViewHeightConstraint.constant = 0
} else {
self.bottomViewHeightConstraint.constant = 108
}
self.view.layoutIfNeeded()
}
Upvotes: 0
Reputation: 7595
As I've mentioned in the comment, you should have used UIStackView
for your top / bottom views visibility controlling.
You will need a UIStackView
with following attributes:
The stack view will contain the Top View, Container View and Bottom View respectively as its sub views.
You need to pin all the sides (leading, trailing, top & bottom) of this stack view to its superview (view controller's view). And as you need some height constraints for your top & bottom view, you give them as your need.
So basically your stack view is now capable of resizing its sub views when you hide any of them. You just need to perform:
theSubViewNeedsTobeHidden.isHidden = true
I've made a working demo for you that can be found here.
Upvotes: 1