使用自定义模式演示处理呼叫状态栏

Aus*_*tin 34 uiview modalviewcontroller ios ios7 ios7-statusbar

问题

我在电话中提出一个UINavigationController(有一个根视图控制器,已经被自然推动)时,我注意到了一些奇怪的行为UIViewControllerAnimatedTransitioning.

  • 如果在显示导航控制器启用了呼叫状态栏,则导航控制器会按预期向下移动其视图.但是当呼叫结束时,控制器不会将其视图向上移动,在状态栏下留下20p的间隙.
  • 如果显示控制器之前启用了通话中状态栏,则控制器根本不会考虑状态栏,而是将44p高导航条中的4p从40p状态栏下方窥视.通话结束后,控制器将其视图向下移动以适应正常的20p状态栏.

*注意:这是在模拟器上测试的,因为它很容易启用/禁用通话状态栏,但测试人员在实际手机上观察到了这种现象.

我的(部分)解决方法

如果状态栏是异常高度,我通过在演示期间调整控制器的框架来解决问题:

@interface CustomAnimationController : NSObject <UIViewControllerAnimatedTransitioning>
@end

@implementation CustomAnimationController

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIViewController *toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *container = [transitionContext containerView];

    CGRect frame = [transitionContext finalFrameForViewController:toController];
    if (CGRectEqualToRect(frame, CGRectZero))
    {
        // In my experience, the final frame is always a zero rect, so this is always hit
        UIEdgeInsets insets = UIEdgeInsetsZero;
        // My "solution" was to inset the container frame by the difference between the 
        // actual status bar height and the normal status bar height
        insets.top = CGRectGetHeight([UIApplication sharedApplication].statusBarFrame) - 20;
        frame = UIEdgeInsetsInsetRect(container.bounds, insets);
    }

    toController.view.frame = frame;
    [container addSubview:toController.view];

    // Perform whiz-bang animation here
}    

@end
Run Code Online (Sandbox Code Playgroud)

此解决方案确保导航栏位于状态栏下方,但导航控制器仍然无法在呼叫结束时自行切换.因此该应用程序至少可以使用,但在通话结束后导航栏上方有一个难看的20p间隙.

有没有更好的办法?

我是否遗漏了一些关键步骤以确保导航控制器自己考虑通话状态栏?当呈现内置的模态演示风格时,它工作得很好.

在我看来,这是一个UIKit错误 - 毕竟,导航控制器似乎收到了UIApplicationWillChangeStatusBarFrameNotification(见问题的第二点).如果其他人遇到这个问题并找到了更好的方法,我将非常感谢一个解决方案.

Fen*_*ski 3

我花了太多时间来解决状态栏高度问题,并提出了一个适合我的通用解决方案,我认为也适合您的情况。

首先,状态栏有一些奇怪的地方。

  1. 通常高度为 20 点,屏幕通常高度为 5 6 8 点

  2. “通话中”时,状态栏高 40 点,屏幕高 5 4 8 点

  3. 状态栏隐藏时,状态栏高 0 点,屏幕高 5 6 8 点

如果状态栏发生变化但您不更新屏幕的高度,那么计算将关闭,这可以在一些相当大的名称(甚至默认)应用程序中看到。

因此,我提出的解决方案有两个: 1. 创建一个宏来获取调整后的屏幕高度 2. 注册通知以在状态栏更改时更新视图。

这是宏,我建议将它们放入您的prefix文件中

#define kScreenWidth     [UIScreen mainScreen].bounds.size.width
#define kStatusBarHeight (([[UIApplication sharedApplication] statusBarFrame].size.height == 20.0f) ? 20.0f : (([[UIApplication sharedApplication] statusBarFrame].size.height == 40.0f) ? 20.0f : 0.0f))
#define kScreenHeight    (([[UIApplication sharedApplication] statusBarFrame].size.height > 20.0f) ? [UIScreen mainScreen].bounds.size.height - 20.0f : [UIScreen mainScreen].bounds.size.height)
Run Code Online (Sandbox Code Playgroud)

此外,我发现以下通知中心调用在状态栏发生变化时 100% 都适用。

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self.view selector:@selector(layoutSubviews) name:UIApplicationWillChangeStatusBarFrameNotification object:nil];
Run Code Online (Sandbox Code Playgroud)