【问题标题】:Handling application:willChangeStatusBarFrame:处理应用程序:willChangeStatusBarFrame:
【发布时间】:2013-02-27 04:06:38
【问题描述】:

在我的应用程序中,我通过简单地缩放整个窗口以适应剩余的屏幕空间来处理状态栏框架的变化:

- (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)];
    }];
}

这可行,但是如果在调用期间窗口被缩小并且我用-presentViewController:animated:completion: 呈现视图控制器,则新控制器不使用缩放坐标系,它使用未缩放坐标系,并且 UI坏了。知道如何让窗口的.transform 转移到呈现的新视图控制器吗?

或者,是否有另一种方法来处理通话状态栏而不重新排列我的所有 UI 元素?

【问题讨论】:

标签: ios scale statusbar uiwindow in-call


【解决方案1】:

每个视图控制器都会将其视图的框架设置为可用空间。处理此问题的最简单方法是确保视图的弹簧和支柱或自动布局属性允许视图的压缩或扩展。随着 iPhone 世界现在包含多种屏幕尺寸,这是一个很好的通用做法。

但是,如果您打算在视图上使用变换来处理大小调整,则可以在视图控制器(可能在公共基类中)中实现 -viewWillLayoutSubviews 以在视图控制器的根视图上设置变换.

编辑

经过调查,通话中状态栏的更改似乎不会导致调用-viewWillLayoutSubviews。但是,以下代码(在通用视图控制器基类中)对我有用:

- (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;
}

【讨论】:

  • 我在使用 UITabBarController 时遇到了问题。好像第一次调用-viewWillLayoutSubviews 时tab bar 还不存在,所以view 的scale 设置的太大了,因为高度是460 计算出来的,而真正用tab bar 控制器,高度是411。
  • 我刚刚使用 UITabBarController 作为根 VC 更新了我的测试项目,它工作正常...您是手动添加标签栏吗?看来您可能需要在此处提供更多代码。
  • 我正在通过情节提要添加标签栏控制器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-13
  • 1970-01-01
  • 2019-09-17
  • 2017-11-25
  • 1970-01-01
  • 1970-01-01
  • 2012-05-01
相关资源
最近更新 更多