3

In my app, I handle the change of the status bar frame by simply scaling the entire window to fit it in the remaining screen space:

- (void)application:(UIApplication *)application willChangeStatusBarFrame:
    (CGRect)newStatusBarFrame {

    UIView* window = [UIApplication sharedApplication].keyWindow;

    [UIView animateWithDuration:1 / 3.f animations:^{
        CGFloat heightDifference = newStatusBarFrame.size.height - 
            kWXDefaultStatusBarHeight;

        [window setTransform:CGAffineTransformMakeScale(1.f, 
            heightScaleForCallStatusBar())];
        [window setFrame:CGRectOffset(window.frame, 0, heightDifference - 
            kWXDefaultStatusBarHeight / 2)];
    }];
}

This works, but if the window is scaled down during a call and I present a view controller with -presentViewController:animated:completion:, the new controller doesn't use the scaled coordinate system, it uses an un-scaled one, and the UI gets broken. Any idea how to get the window's .transform to transfer to new view controllers that are presented?

Alternatively, is there another way to handle the in-call status bar without re-arranging all of my UI elements?

eric.mitchell
  • 8,817
  • 12
  • 54
  • 92
  • What is "in-call"? — Oh, you mean a *phone* call! – matt Apr 08 '13 at 23:39
  • Really just a duplicate of http://stackoverflow.com/questions/5486491/how-in-call-status-bar-impacts-uiviewcontrollers-view-size-and-how-to-handle – matt Apr 08 '13 at 23:41

1 Answers1

3

Each view controller will have its view's frame set to the available space. The simplest way to handle this is to make sure that your view's springs-and-struts or autolayout properties allow for compression or expansion of the view. With the iPhone world now including multiple screen sizes, this is a good general practice.

However, if you are intent on using a transform on your view to handle resizing, you can implement -viewWillLayoutSubviews in your view controllers (probably in a common base class) to set a transform on the root view of the view controller.

Edit:

On investigation, it appears that in-call status bar changes are not causing -viewWillLayoutSubviews to be called. However, the following code (in a common view controller base class) is working for me:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(statusFrameChanged:)
                                                 name:UIApplicationWillChangeStatusBarFrameNotification
                                               object:nil];
}

- (void)viewDidUnload
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIApplicationWillChangeStatusBarFrameNotification
                                                  object:nil];
    [super viewDidUnload];
}

- (void)statusFrameChanged:(NSNotification*)note
{
    CGRect statusBarFrame = [note.userInfo[UIApplicationStatusBarFrameUserInfoKey] CGRectValue];
    CGFloat statusHeight = statusBarFrame.size.height;

    UIScreen *screen = [UIScreen mainScreen];
    CGRect viewRect = screen.bounds;

    viewRect.size.height -= statusHeight;
    viewRect.origin.y = statusHeight;
    self.view.frame = viewRect;
    [self.view setNeedsLayout];
}

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    CGRect baseFrame = self.view.frame;
    // 548.0 is the full height of the view.  Update as necessary.
    CGFloat scale = self.view.frame.size.height / 548.0;
    [self.view setTransform:CGAffineTransformMakeScale(1.0, scale)];
    self.view.frame = baseFrame;
}
Seamus Campbell
  • 17,816
  • 3
  • 52
  • 60
  • I'm having trouble with this with UITabBarController. It seems like the first time -viewWillLayoutSubviews is called the tab bar doesn't exist yet, so the view's scale is set too large because the height is calculated at 460 when really with the tab bar controller, the height is 411. – eric.mitchell Apr 09 '13 at 15:47
  • I just updated my test project with a UITabBarController as the root VC and it's working fine... are you adding the tab bar manually? Seems like you might need to provide more code here. – Seamus Campbell Apr 09 '13 at 19:40
  • I'm adding my tab bar controller through a storyboard. – eric.mitchell Apr 10 '13 at 01:13