Reputation: 341
I have a view controller view with 3 column sections (called legs, aView
, bView
, and cView
) by default. The user can switch it between 2 and 3 in a settings menu that gets presented modally over the same screen.
I'm trying to get the columns to take up space equally on the screen, so when there are 3 columns, they each take up roughly 1/3 of the width (ignoring padding), and when there are 2, they each take up roughly 1/2.
My current method is setting some constraints that are always active, and then for the ones that change depending on the number of columns, using an if
statement. I tried some variations of layoutIfNeeded()
, removeConstraints
, and others but not entirely sure how to implement them.
For some clarification on the code, xView
is the column view, which contains xTitle
and xTextView
. There is also a mainButton
above the text views, and button1
below the text views. This all exists inside a contentView
and scrollView
setup.
let sidePadding: CGFloat = 15
func placeViews() { // run in viewWillAppear
let alwaysConstraints = [
aView.topAnchor.constraint(equalTo: mainButton.bottomAnchor, constant: 25),
aView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: sidePadding),
aView.rightAnchor.constraint(equalTo: bView.leftAnchor),
bView.topAnchor.constraint(equalTo: aView.topAnchor),
bView.bottomAnchor.constraint(equalTo: aView.bottomAnchor),
aTitle.topAnchor.constraint(equalTo: aView.topAnchor),
bTitle.topAnchor.constraint(equalTo: aTitle.topAnchor),
aTitle.centerXAnchor.constraint(equalTo: aView.centerXAnchor),
bTitle.centerXAnchor.constraint(equalTo: bView.centerXAnchor),
aTextView.topAnchor.constraint(equalTo: aTitle.bottomAnchor, constant: 25),
bTextView.topAnchor.constraint(equalTo: aTextView.topAnchor),
aTextView.bottomAnchor.constraint(equalTo: aView.bottomAnchor),
bTextView.bottomAnchor.constraint(equalTo: aTextView.bottomAnchor),
aTextView.centerXAnchor.constraint(equalTo: aView.centerXAnchor),
bTextView.centerXAnchor.constraint(equalTo: bView.centerXAnchor),
aTextView.widthAnchor.constraint(equalTo: aView.widthAnchor),
bTextView.widthAnchor.constraint(equalTo: bView.widthAnchor),
bView.widthAnchor.constraint(equalTo: aView.widthAnchor),
// Restrict buttons to leg views
button1.heightAnchor.constraint(equalToConstant: buttonHeight),
button1.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
button1.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
button1.topAnchor.constraint(equalTo: aView.bottomAnchor, constant: 40),
// Restrict button to bottom
button1.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20)
]
let twoLegConstraints = [
aView.widthAnchor.constraint(equalToConstant: (view.frame.width - (sidePadding * 2) / 2)),
bView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -sidePadding),
]
let threeLegConstraints = [
aView.widthAnchor.constraint(equalToConstant: (view.frame.width - (sidePadding * 2)) / 3),
bView.rightAnchor.constraint(equalTo: cView.leftAnchor),
cView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -sidePadding),
cView.topAnchor.constraint(equalTo: aView.topAnchor),
cView.bottomAnchor.constraint(equalTo: aView.bottomAnchor),
cTitle.topAnchor.constraint(equalTo: aTitle.topAnchor),
cTitle.centerXAnchor.constraint(equalTo: cView.centerXAnchor),
cTextView.topAnchor.constraint(equalTo: aTextView.topAnchor),
cTextView.bottomAnchor.constraint(equalTo: aTextView.bottomAnchor),
cTextView.centerXAnchor.constraint(equalTo: cView.centerXAnchor),
cTextView.widthAnchor.constraint(equalTo: cView.widthAnchor),
cView.widthAnchor.constraint(equalTo: aView.widthAnchor),
]
NSLayoutConstraint.activate(alwaysConstraints)
if legs == 2 {
cView.isHidden = true
NSLayoutConstraint.activate(twoLegConstraints)
} else if legs == 3 {
cView.isHidden = false
NSLayoutConstraint.activate(threeLegConstraints)
}
}
At the moment, the screen starts with 3 by default, and it works perfectly (each ~1/3 screen width). Then the user can switch it to 2, and it works perfectly again (each ~1/2 screen width). Then switching back to 3, the first two don't change at all, and the third column appears on the right edge of the screen.
Upvotes: 0
Views: 50
Reputation: 19882
Use a stack view with distribution = .fillEqually
. It will take care of the layout and constraints automatically when you set the isHidden
property of any of your views.
Upvotes: 1