How can I make my view resize in response to the in-call status bar from my nib?
I figured it would just be setting the resize properties, but they\'re not enabled f
You will have to update the views manually if you are setting your view frames programatically
-(void) viewDidAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarFrameWillChange:)name:UIApplicationWillChangeStatusBarFrameNotification object:nil];
}
- (void)statusBarFrameWillChange:(NSNotification*)notification
{
// respond to changes
NSLog(@"STATUS BAR UPDATED");
NSDictionary *statusBarDetail = [notification userInfo];
NSValue *animationCurve = statusBarDetail[UIApplicationStatusBarFrameUserInfoKey];
CGRect statusBarFrameBeginRect = [animationCurve CGRectValue];
int statusBarHeight = (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication]statusBarOrientation])) ? statusBarFrameBeginRect.size.height : statusBarFrameBeginRect.size.width;
NSLog(@"status bar height %d", statusBarHeight);
}
-(void) viewDidDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationBackgroundRefreshStatusDidChangeNotification object:nil];
}
This gives you the new height of the status bar and using this you can update your frames accordingly.
A view may not resize automatically with status bar size changes if you do not have a root view controller set. I originally had this in my app delegate, and my app worked properly in all regards except that it would not resize correctly during phone calls.
[self.window addSubview:rootController.view];
I changed the above line to this, and now my app resizes automatically during calls.
[self.window setRootViewController:rootController];
I discovered this fix after seeing this in the log and investigating the cause.
Application windows are expected to have a root view controller at the end of application launch
The notification for status bar changing frame is
UIApplicationWillChangeStatusBarFrameNotification
Register as an observer:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarFrameWillChange:)name:UIApplicationWillChangeStatusBarFrameNotification object:nil];
Then respond to change in your handler:
- (void)statusBarFrameWillChange:(NSNotification*)notification
{
// respond to changes
}
Even with autolayout setup correctly, you may need to respond to changes. For example, a table view that calculates its cell height based on the given space in the screen would may need to reloadData
after the status bar changed.
Documentation
For views like UITableView you'll typically need to change the table cell height, and there's no other way to do it except to implement application:didChangeStatusBarFrame:. But it's no biggie, and you can set the row height to non-integer values if you need to.
What do you mean when you say that 'the resize properties aren't enabled for the root UIView'?
The in-call status bar doesn't have any particular special designation, and I don't think there are any APIs or notifications around it. Instead, your views should simply be set up to autoresize correctly.
Try creating a new navigation-based app in Xcode and study the autoresize settings on the table view in RootViewController.xib. Hopefully you'll see a delta between what Apple's set and what you've set in your project.
iOS will invoke your viewController's viewWillLayoutSubviews method whenever there is a change in status bar. You can override that and adjust your subviews according to the new bounds.
- (void)viewWillLayoutSubviews {
// Your adjustments accd to
// viewController.bounds
[super viewWillLayoutSubviews];
}