Ios 使用自定义模式表示在呼叫状态栏中进行处理 问题

Ios 使用自定义模式表示在呼叫状态栏中进行处理 问题,ios,uiview,ios7,modalviewcontroller,ios7-statusbar,Ios,Uiview,Ios7,Modalviewcontroller,Ios7 Statusbar,我注意到一些奇怪的行为,当在通话中使用UIViewControllerAnimatedTransitioning呈现UINavigationController(带有根视图控制器,自然已按下)时 如果在显示导航控制器后启用了呼叫内状态栏,则导航控制器会按预期向下移动其视图。但当通话结束时,控制器不会将其视图向上移动,在状态栏下留下20p的间隙 如果在显示控制器之前启用了呼叫内状态栏,则控制器根本不考虑状态栏,使44p高导航栏的4p从40p状态栏下方向外窥视。呼叫结束时,控制器向下移动视图以适应

我注意到一些奇怪的行为,当在通话中使用
UIViewControllerAnimatedTransitioning
呈现
UINavigationController
(带有根视图控制器,自然已按下)时

  • 如果在显示导航控制器后启用了呼叫内状态栏,则导航控制器会按预期向下移动其视图。但当通话结束时,控制器不会将其视图向上移动,在状态栏下留下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
@interface CustomAnimationController:NSObject
@结束
@CustomAnimationController的实现
-(void)animateTransfion:(id)transitionContext
{
UIViewController*toController=[transitionContext ViewControllerWorky:UITransitionContextToViewControllerKey];
UIView*容器=[transitionContext containerView];
CGRect frame=[transitionContext finalFrameForViewController:toController];
if(CGRectEqualToRect(帧,CGRectZero))
{
//根据我的经验,最后一帧总是一个零矩形,所以这总是命中的
UIEdgeInsets insets=UIEdgeInsetsZero;
//我的“解决方案”是通过两个容器之间的差异插入容器框架
//实际状态栏高度和正常状态栏高度
insets.top=CGRectGetHeight([UIApplication sharedApplication].statusBarFrame)-20;
frame=uiedgeinsetinsetrect(container.bounds,insets);
}
toController.view.frame=frame;
[容器添加子视图:toController.view];
//在这里执行whiz-bang动画
}    
@结束
此解决方案可确保导航栏位于状态栏下方,但在通话结束时导航控制器仍无法将自身向上移动。因此,该应用程序至少是可用的,但在通话结束后,导航栏上方有一个丑陋的20便士的差距

有更好的办法吗? 我是否错过了一些关键步骤,以确保导航控制器能够自行解释通话中的状态栏?当使用内置的模态表示样式表示时,它可以正常工作


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

我花了太多时间来解决状态栏高度问题,并提出了一个通用的解决方案,该方案对我有效,我想也适用于您的情况

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

  • 它通常高20点,屏幕通常高568点

  • “通话”时,状态栏高40点,屏幕高548点

  • 当状态栏处于隐藏状态时,状态栏的高度为0点,屏幕的高度为568点

  • 如果状态栏改变了,但是你没有更新屏幕的高度,那么计算将被关闭,这可以在一些非常有名(甚至是默认)的应用程序中看到

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

    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self.view selector:@selector(layoutSubviews) name:UIApplicationWillChangeStatusBarFrameNotification object:nil];
    
    下面是宏,我建议将它们放在
    前缀文件中

    #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)
    
    此外,我发现通知中心的呼叫在状态栏更改的情况下100%适用于我

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

    只需在LayoutSubview中设置状态栏高度更改时调用的框架。通常,根据经验,仅在LayoutSubview中进行所有帧设置。

    以下是我在app delegate中提出的一个解决方法,它为我解决了这个问题:

    - (void)application:(UIApplication *)application willChangeStatusBarFrame:(CGRect)newStatusBarFrame
    {
        if (newStatusBarFrame.size.height < 40) {
            for (UIView *view in self.window.subviews) {
                view.frame = self.window.bounds;
            }
        }
    }
    
    -(void)应用程序:(UIApplication*)应用程序将更改状态栏框架:(CGRect)新闻状态栏框架
    {
    if(newStatusBarFrame.size.height<40){
    用于(UIView*self.window.subview中的视图){
    view.frame=self.window.bounds;
    }
    }
    }
    
    我也遇到了同样的问题,问题在于我所呈现的视图,由于在调用栏中,视图自动调整了20磅。然而,由于我将视图插入到容器中,我必须重置框架以匹配容器的边界

    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
        UIView* destinationView = [transitionContext viewForKey:UITransitionContextToViewKey];
        UIView* container = transitionContext.containerView;
    
        // Make sure destination view matches container bounds
        // This is necessary to fix the issue with in-call bar
        // which adjusts the view's frame by 20pt.
        destinationView.frame = container.bounds;
    
        // Add destination view to container
        [container insertSubview:destinationView atIndex:0];
    
        // [reducted]
    }
    
    -(void)animateTransfion:(id)transitionContext{
    UIView*destinationView=[transitionContext viewForKey:UITransitionContextToViewKey];
    UIView*container=transitionContext.containerView;
    //确保目标视图与容器边界匹配
    //这是修复调用栏中的问题所必需的
    //将视图的帧调整20磅。
    destinationView.frame=container.bounds;
    //将目标视图添加到容器
    [容器插入子视图:destinationView索引:0];
    //[减少]
    }
    
    我也有同样的问题,我通过调用“更新帧视图”修复了它,所以我得到了高度状态栏。我的问题解决了

     UIView *toViewSnapshot = [toView resizableSnapshotViewFromRect:toView.frame afterScreenUpdates:YES withCapInsets:UIEdgeInsetsZero];
    

    你找到解决办法了吗?我的问题是,我的应用程序的主屏幕没有导航栏,带有一个滑入式面板,其中确实有一个导航栏。当滑入面板全屏显示时,呼叫进行中绿色条显示