I'd like to ask about Auto Layout and in-call status bar. Here's a simple scenario that demonstrates my problem:
- Create project with "Use Storyboards" enabled
- Add "View Controller" and enable its "Is Initial View Controller"
- Set background color of controller's view to red
- Add "Table View" into controller's view
The table view should have 4 layout constraints (leading, top, trailing, bottom) to Superview with constant set to 0.
Now when I run this app in Simulator and press ⌘ + T I can see red background while the in-call status bar animates in. Is it possible to get rid of this glitch?
(Using answer instead of comment due to lack of reputation, sorry.)
I ran into this issue as well and was trying out e.g. the solution pointed out above: It didn't work for me.
So I created a repository with example code to expose the original poster's problem. There are example applications for these scenarios:
- the Custom View Controller is the window's root view controller,
- the Custom View Controller is a child of a UINavigationController which is the window's root view controller,
- the Custom View Controller is a child of a UITabBarController which is the window's root view controller and
- the Custom View Controller is a child of a UINavigationController which is as child of a UITabBarController which is the window's root view controller.
It turned out that the solution from CEarwood actually works… when the custom view controller is a child of a UINavigationController (cases 2 and 4). Hoewever, it does not work in cases 1 and 3.
I hope this information is useful.
For a purely Auto Layout answer you can get a reference to the bottom constraint and adjust its constant when UIApplicationWillChangeStatusBarFrameNotification is received and back to 0 when the DidChange notification is received. Here's the test VC I used:
@interface CEViewController ()
@property (nonatomic, strong) IBOutlet NSLayoutConstraint *bottomConstraint;
@end
@implementation CEViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarFrameWillChange:) name:UIApplicationWillChangeStatusBarFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarFrameDidChange:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
}
- (void)statusBarFrameWillChange:(NSNotification *)note {
NSValue *newFrameValue = [note userInfo][UIApplicationStatusBarFrameUserInfoKey];
self.bottomConstraint.constant = newFrameValue.CGRectValue.size.height;
[self.view setNeedsLayout];
}
- (void)statusBarFrameDidChange:(NSNotification *)note {
self.bottomConstraint.constant = 0;
[self.view setNeedsLayout];
}
@end
This is an effect from the screen resizing.
When the in-call status bar appears, the view resizes to the size it should have with the in-call status bar active and then moves down as the status bar changes size.
For a brief moment, the view under the table view is visible. What you could do is add a view under the table view extending downwards out of the screen to cover-up the background color.
Another approach is with your AppDelegate
, implement:
-application:willChangeStatusBarFrame:
and resize the table view to cover the bit that gets exposed. Then when -application:didChangeStatusBarFrame:
gets called, resize it back to the original size.