Auto Layout and in-call status bar

2019-01-23 14:51发布

I'd like to ask about Auto Layout and in-call status bar. Here's a simple scenario that demonstrates my problem:

  1. Create project with "Use Storyboards" enabled
  2. Add "View Controller" and enable its "Is Initial View Controller"
  3. Set background color of controller's view to red
  4. 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?

3条回答
我命由我不由天
2楼-- · 2019-01-23 14:57

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.

查看更多
虎瘦雄心在
3楼-- · 2019-01-23 15:04

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
查看更多
放我归山
4楼-- · 2019-01-23 15:16

(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:

  1. the Custom View Controller is the window's root view controller,
  2. the Custom View Controller is a child of a UINavigationController which is the window's root view controller,
  3. the Custom View Controller is a child of a UITabBarController which is the window's root view controller and
  4. 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.

查看更多
登录 后发表回答