问题
With iOS 8 Apple introduced size classes for handling layouts of an app. Instead of designing user interfaces dependent on device, screen size, and orientation, developers are encouraged to rather adapt their app's layout depending on the active size classes. That's a good move, I think.
However, when it comes to the iPad there seem to be no way to distinguish the different device orientations (which provide quite different screen space and handling in my opinion). From the Human Interface Guidelines:
What am I supposed to do now if I want to present a side menu only in landscape orientation because it provides more space, like aUISplitViewController
?
Is the UISplitViewController
another case where Apple doesn't eat it's own dog food and uses some other metrics like the device orientation or the actual screen width to determine the layout? Or is there another, official way to do that? Something I could do in Interface Builder alone without code?
(And no, I don't want to use UISplitViewController
for several reasons.)
回答1:
This is how I resolved the issue you're having:
Use a different size class to add the constraints for portrait and landscape (which you seem to be doing) then create an IBOutletCollection
for the constraints for each size class that are based on the orientation.
For example, I used wAnyhRegular to setup my portrait iPad layout and then used wRegularhAny to setup my landscape iPad layout. (Although you may want to use wRegular/hRegular as one of your orientation layouts since iPad registers as wRegular/hRegular when you check the UITraitCollection
. Hopefully the code below demonstrates how I went about it:
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *iPadPortraitConstraints;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *iPadLandscapeConstraints;
My portrait constraints can be seen below. My landscape has 3 constraints as well.
I then apply the constraints as noted below (not shown, viewDidLoad executes _needsiPadConstraintsApplied = YES;
):
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
[self applyiPadConstraints];
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
// Size Classes does not support differentiating between iPad Portrait & Landscape.
// Signal that the iPad rotated so we can manually change the constraints.
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
_needsiPadConstraintsApplied = YES;
}
}
- (void)applyiPadConstraints {
if (_needsiPadConstraintsApplied) {
if (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)) {
[NSLayoutConstraint deactivateConstraints:self.iPadLandscapeConstraints];
[NSLayoutConstraint activateConstraints:self.iPadPortraitConstraints];
} else {
[NSLayoutConstraint deactivateConstraints:self.iPadPortraitConstraints];
[NSLayoutConstraint activateConstraints:self.iPadLandscapeConstraints];
}
_needsiPadConstraintsApplied = NO;
}
}
来源:https://stackoverflow.com/questions/31189792/distinguish-ipad-orientation-with-size-classes