In portrait mode I have four views on top of one another from the top to the bottom of the view controller (see image).
I then want to change the position o
I use arrays of constraints and activate/deactivate according to orientation.
var p = [NSLayoutConstraint]()
var l = [NSLayoutConstraint]()
var initialOrientation = true
var isInPortrait = false
override func viewDidLoad() {
super.viewDidLoad()
// add any subviews here
view.turnOffAutoResizing()
// add constraints here....
// common constraints you can set their isActive = true
// otherwise, add in to portrait(p) and landscape(l) arrays
}
override func viewWillLayoutSubviews() {
super.viewDidLayoutSubviews()
if initialOrientation {
initialOrientation = false
if view.frame.width > view.frame.height {
isInPortrait = false
} else {
isInPortrait = true
}
view.setOrientation(p, l)
} else {
if view.orientationHasChanged(&isInPortrait) {
view.setOrientation(p, l)
}
}
}
extension UIView {
public func turnOffAutoResizing() {
self.translatesAutoresizingMaskIntoConstraints = false
for view in self.subviews as [UIView] {
view.translatesAutoresizingMaskIntoConstraints = false
}
}
public func orientationHasChanged(_ isInPortrait:inout Bool) -> Bool {
if self.frame.width > self.frame.height {
if isInPortrait {
isInPortrait = false
return true
}
} else {
if !isInPortrait {
isInPortrait = true
return true
}
}
return false
}
public func setOrientation(_ p:[NSLayoutConstraint], _ l:[NSLayoutConstraint]) {
NSLayoutConstraint.deactivate(l)
NSLayoutConstraint.deactivate(p)
if self.bounds.width > self.bounds.height {
NSLayoutConstraint.activate(l)
} else {
NSLayoutConstraint.activate(p)
}
}
}
My needs to distinguish portrait or landscape require using something other than size classes, as my app is universal and iPad (unless using split or slide out view) is always normal size. Also, you may get use viewWillTransistion(toSize:) or viewDidLoadSubviews() instead of 'viewWillLoadSubviews()` - but always test, as these may be executed more than once on an orientation change!