In our app, we temporarily hide the status bar as part of the animation between transitioning between two screens that both need different status bar styles.
We have a percent driven animation transition which when started, hides the status bar with animation and when finish re shows the status bar.
On iOS 11 the safe area insets include the status bar height which can be variable, and when hidden the top inset of the safe area drops to 0 height. This re-adjusts all our views and has a horrible jump between view sizes.
We still want to constrain our views to the safe area since we're trying to support iPhone X.
Can we temporarily disable the change to the safe area insets when hiding the status bar?
Try add 2 constraints:
1) view - superview
2) view - safeArea
Constraints that are set to the safe area are affected by the status bar as well as the views actual location on the screen and its transform. If you always want to just apply the top (or bottom) safe area height to your view constraint, you can do this by use of a custom constraint instead.
The following constraint will automatically set its constant
value to the height of the device's top safe area height, not affected by the status bar or other parameters. To use it, change the class of any constraint into this, and their constant
will always be the safe area height. Note that it will not change its value when the device is rotated.
Objective-C
@interface TopSafeAreaContraint : NSLayoutConstraint
@end
@implementation TopSafeAreaContraint
- (void)awakeFromNib {
[super awakeFromNib];
if (@available(iOS 11.0, *)) {
UIEdgeInsets insets = [UIApplication sharedApplication].keyWindow.safeAreaInsets;
self.constant = MAX(insets.top, 20.0);
} else {
// Pre-iOS 11.0
self.constant = 20.0;
}
}
@end
Swift
class TopSafeAreaConstraint: NSLayoutConstraint {
override func awakeFromNib() {
super.awakeFromNib()
if #available(iOS 11.0, *) {
let insets = UIApplication.shared.keyWindow?.safeAreaInsets ?? .zero
self.constant = max(insets.top, 20)
} else {
// Pre-iOS 11.0
self.constant = 20.0
}
}
}
I've been experiencing a similar issue so I came up with a slightly different approach. This is not a direct answer to the problem. It is a workaround which worked in my case.
I had two different view controllers, both of which must have a navigation bar (but a navigation controller is not required). The 1st view controller is presenting the 2nd one in a modal fashion. The problem is that the 2nd view controller is landscape only, which means that on iPhones with edge-to-edge displays any overrides of prefersStatusBarHidden
are ignored and the system always returns true
(see here).
What I did was simulate the status bar height through a custom view, and then adjust the height constraint constant in viewDidLoad(_:)
.
I got no ugly navbar or view controller jumps after that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With