With iOS 8 and Xcode 6, in storyboards we now have the screen size grid letting us select a size class. Where you can select layout formatting for the different screen sizes.
I have found this brilliantly helpful, as it allows me to set the base constraints and then unique ones for each screen size.
My question is, can you do this programmatically? I create my NSLayoutConstraint
as normal but I need to be able to specify different constraints for different screen sizes.
iOS 8 introduces the active
property on NSLayoutConstraint
. It allows you to activate or deactivate a constraint. There are also methods to activate/deactivate multiple constraints.
+ (void)activateConstraints:(NSArray *)constraints
+ (void)deactivateConstraints:(NSArray *)constraints
- Keep your constraints in arrays when creating them programmatically.
- Create an array for each of the layouts you need.
- Activate/Deactivate whatever set of constraints you need from within
willTransitionToTraitCollection
To answer your question, you can set the size class programmatically, however, it's a bit of a pain. You must call "setOverrideTraitCollection" but from the parent view controller, not the one you actually wished to make a trait change to.
In my situation, I wanted to change the Master VC of a split view controller on iPad to look differently than the one on the iPhone, however, they are both set to Compact width / Regular height by default. So I subclassed the Master's nav controller and added code to set the Master's traits to Regular width when it's not an iPhone.
Swift code:
class MasterNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
if (self.traitCollection.userInterfaceIdiom != .Phone) {
let newTraitCollection = UITraitCollection(horizontalSizeClass: .Regular)
self.setOverrideTraitCollection(newTraitCollection, forChildViewController: self.topViewController)
}
}
}
I hope this helps someone looking for a similar solution.
It's a bit confusing & hard to find in the documentation because a "size class" isn't actually a "Class" like NSObject. They're really defined in an enum/typedef called: UIUserInterfaceSizeClass
The way to get the horizontal & vertical size class for a view is with a UITraitCollection
Class/Type methods for UITraitCollection allow you to create one based on a particular display scale (e.g. retina or not), from an array of other trait collections, with a UI idiom (iPad/iPhone), or specific horizontal & vertical options (compact, regular), but to be honest I'm not sure yet how you'd use this...
This question discusses updating constraints when the traitCollection changes, using willTransitionToTraitCollection(newCollection: UITraitCollection!,
withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator!)
You're right that both the UITraitCollection and its properties are readonly, but clearly you can create a new collection for some reason, and handle layout changes when the traitCollection changes.
This previous question is pretty similar & links to an Apple article about using Adaptive Layout. Also check the WWDC video "Building Adaptive Apps with UIKit."
来源:https://stackoverflow.com/questions/26363057/set-autolayout-size-class-programmatically