I have created a View Controller with a segmented controller at the top. When you tap the segmented controller it just acts as a button and changes whether the imageView inside of the controller is portrait mode or in landscape mode just by calling a function that changes it to the according dimensions.
My problem is that the way I made it change is I just added contraints to the imageView, but when changing to landscape mode the trailing constraint doesn't get removed.
And, this is the code to change the imageView to portrait (The imageView already has the top and bottom contraints on it) :
func portraitContraints() {
NSLayoutConstraint.activate ([
// the trailing contraint
imageView.trailingAnchor.constraint(equalTo: viewContainer.safeAreaLayoutGuide.trailingAnchor, constant: -75), // this is the contraints that doesn't get removed
// the leading contraints
imageView.leadingAnchor.constraint(equalTo: viewContainer.safeAreaLayoutGuide.leadingAnchor, constant: 75
])
// the aspect ratio contraints
imageView.addConstraint(NSLayoutConstraint(item: self.imageView as Any,attribute: .height,relatedBy: .equal,toItem: self.imageView,attribute: .width,multiplier: (4.0 / 3.0),constant: 0))
}
This is the code to change the imageView to landscape:
func landscapeContraints() {
NSLayoutConstraint.activate([
// the trailing contraints
imageView.trailingAnchor.constraint(equalTo: viewContainer.safeAreaLayoutGuide.trailingAnchor, constant: 0),
// the leading contraint
imageView.leadingAnchor.constraint(equalTo: viewContainer.safeAreaLayoutGuide.leadingAnchor, constant: 0)
])
// the aspect ratio contraint
imageView.addConstraint(NSLayoutConstraint(item: self.imageView as Any,attribute: .height,relatedBy: .equal,toItem: self.imageView,attribute: .width,multiplier: (9.0 / 16.0),constant: 0))
}
This code works like a charm, except the only problem is that the trailing constraint from the portrait mode will stay on the view (the -75 constant constraint).
Landscape looks like this (notice the right side constant is -75):
Portrait looks like this:
You can do this by adding both ratio constraints, with different priorities. Change the priorities to make the desired ratio "active".
And, create leading and trailing constraint vars, so you can change their constants.
Here's a quick example:
class ToggleConstraintsViewController: UIViewController {
let imageView = UIImageView()
var isPortrait: Bool = true
var portraitConstraint: NSLayoutConstraint!
var landscapeConstraint: NSLayoutConstraint!
var leadingConstraint: NSLayoutConstraint!
var trailingConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
imageView.backgroundColor = .blue
imageView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(imageView)
let g = view.safeAreaLayoutGuide
portraitConstraint = imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: 4.0/3.0)
portraitConstraint.priority = .defaultHigh
landscapeConstraint = imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: 9.0/16.0)
landscapeConstraint.priority = .defaultLow
leadingConstraint = imageView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 75.0)
trailingConstraint = imageView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -75.0)
NSLayoutConstraint.activate([
// y-position constraint does not change
imageView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
// these will have their priorities changed when desired
portraitConstraint,
landscapeConstraint,
// these will have their constants changed when desired
leadingConstraint,
trailingConstraint,
])
let t = UITapGestureRecognizer(target: self, action: #selector(self.toggleOrientation(_:)))
view.addGestureRecognizer(t)
}
@objc func toggleOrientation(_ g: UITapGestureRecognizer) -> Void {
isPortrait.toggle()
portraitConstraint.priority = isPortrait ? .defaultHigh : .defaultLow
landscapeConstraint.priority = isPortrait ? .defaultLow : .defaultHigh
leadingConstraint.constant = isPortrait ? 75.0 : 0.0
trailingConstraint.constant = isPortrait ? -75.0 : 0.0
}
}
Each time you tap the view, the imageView's width:height ratio will change, and the leading/trailing constraint constants will change.