UIViewController呼入状态栏问题

问题:

在通话状态栏消失之后,模式提供的视图控制器不会恢复,在顶部留下20px的空白/透明空间。


正常:没有问题

在这里输入图像说明


通话中:没有问题

在这里输入图像说明


在通话消失后:

在顶部留下20px高的空白/透明空间,显示下方的橙色视图。 但状态栏仍然存在于透明区域。 导航栏还留下状态栏的空间,其“仅20px太低的位置。

在这里输入图像说明

在这里输入图像说明


  • 基于iOS 10
  • 模态呈现的视图控制器
  • 自定义模态演示
  • 主视图控制器后面是橙色的
  • 不使用Autolayout
  • 当旋转到横向 ,20px呼叫栏离开,仍然留下20px的差距。
  • 我select了在风景方向显示状态栏。 (即大多数股票应用程序)

我试着听应用程序代表:

willChangeStatusBarFrame didChangeStatusBarFrame 

还查看基于控制器的通知:

 UIApplicationWillChangeStatusBarFrame UIApplicationDidChangeStatusBarFrame 

当我为上述所有四种方法logging出现视图的框架时,框架总是在(y:0)原点。


更新

视图控制器自定义模态演示

  let storyboard = UIStoryboard(name: "StoryBoard1", bundle: nil) self.modalVC = storyboard.instantiateViewController(withIdentifier: "My Modal View Controller") as? MyModalViewController self.modalVC!.transitioningDelegate = self self.modalVC.modalPresentationStyle = .custom self.modalVC.modalPresentationCapturesStatusBarAppearance = true; self.present(self.modalVC!, animated: true, completion: nil) func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let containerView = transitionContext.containerView let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) toViewController!.view.transform = CGAffineTransform(scaleX: 0.001, y: 0.001) UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.0, options: [.curveEaseOut], animations: { () -> Void in toViewController!.view.transform = CGAffineTransform.identity }, completion: { (completed) -> Void in transitionContext.completeTransition(completed) }) } 

我与修改状态栏的个人hospot有同样的问题。 解决办法是向系统注册状态栏框的更改通知,这将允许您更新您的布局,并应解决您可能有任何布局问题。 我的解决scheme应该为你完全一样的是这样的:

  • 在你的视图控制器中,在viewWillAppear订阅UIApplicationDidChangeStatusBarFrameNotification

      NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(myControllerName.handleFrameResize(_:)), name: UIApplicationDidChangeStatusBarFrameNotification, object: nil) 
  • 创build你的select器方法

     func handleFrameResize(notification: NSNotification) { self.view.layoutIfNeeded() } 
  • viewWillDisappear通知中心删除您的控制器viewWillDisappear

      NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationDidChangeStatusBarFrameNotification, object: nil) 
  • 你也需要你的模态负责状态栏,所以你应该设置

    在呈现视图之前, destVC.modalPresentationCapturesStatusBarAppearance = true

你可以在每个控制器上实现这个状态栏上的变化,或者你可以创build另外一个类来完成每个控制器的工作,比如将自己传递给一个方法,保持引用改变布局并且有一个方法去除自我。 你知道,为了重用代码。

我也面临这个问题,但是在我把这个方法之后,问题就消失了。

iOS有其默认方法willChangeStatusBarFrame来处理状态栏。 请把这个方法,并检查它。

 func application(_ application: UIApplication, willChangeStatusBarFrame newStatusBarFrame: CGRect) { UIView.animate(withDuration: 0.35, animations: {() -> Void in let windowFrame: CGRect? = ((window?.rootViewController? as? UITabBarController)?.viewControllers[0] as? UINavigationController)?.view?.frame if newStatusBarFrame.size.height > 20 { windowFrame?.origin?.y = newStatusBarFrame.size.height - 20 // old status bar frame is 20 } else { windowFrame?.origin?.y = 0.0 } ((window?.rootViewController? as? UITabBarController)?.viewControllers[0] as? UINavigationController)?.view?.frame = windowFrame }) } 

希望这件事能帮助你。
谢谢

我认为这是UIKit中的一个错误。 包含使用自定义转换呈现的呈现的控制器视图的containerView在状态栏恢复到正常大小时似乎没有完全移回。 (您可以在closures通话状态栏后检查视图层次结构)

为了解决这个问题,你可以提供一个自定义的演示控制器。 然后,如果您不需要呈现控制器的视图保留在视图层次结构中,则只需为呈现控制器的shouldRemovePresentersView属性返回true ,就是这样。

 func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { return PresentationController(presentedViewController: presented, presenting: presenting) } class PresentationController: UIPresentationController { override var shouldRemovePresentersView: Bool { return true } } 

或者如果您需要保留呈现控制器的视图,则可以观察状态栏框架更改并手动调整containerView以使其与超级视图的大小相同

 class PresentationController: UIPresentationController { override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) { super.init(presentedViewController: presentedViewController, presenting: presentingViewController) NotificationCenter.default.addObserver(self, selector: #selector(self.onStatusBarChanged), name: .UIApplicationWillChangeStatusBarFrame, object: nil) } @objc func onStatusBarChanged(note: NSNotification) { //I can't find a way to ask the system for the values of these constants, maybe you can if UIApplication.shared.statusBarFrame.height <= 20, let superView = containerView?.superview { UIView.animate(withDuration: 0.4, animations: { self.containerView?.frame = superView.bounds }) } } } 

我一直在寻找解决这个问题的方法。 在面对,我发布了一个类似这个新的问题。 在这里: 如何避免iOS的蓝色位置NavigationBar搞砸了我的状态栏?

相信我,我已经解决了这一两天了,真的很烦人,因为通过呼叫,热点和位置的iOS状态栏更改,你的屏幕搞砸了。

我已经尝试过实现Modi的答案,我把这段代码放在我的AppDelegate中,并修改了一下,但没有运气。 我相信iOS会自动完成,所以你不必自己实现。

在我发现问题的罪魁祸首之前,我曾经尝试过这个问题的每个解决scheme。 不需要实现AppDelegate的方法willChangeStatusBar...或者添加一个通知来观察statusBar的变化。

我也做了重做我的项目的一些stream程,通过编程(我正在使用故事板)做一些屏幕。 我试了一下,然后检查了我以前和其他目前的项目为什么他们正在做适当的调整:)

底线是 :我用UITabBarController以这种错误的方式呈现我的主屏幕。

请始终注意模式的modalPresentationStyle 。 由于诺亚的评论,我有了想看看我的代码的想法。

样品:

 func presentDashboard() { if let tabBarController = R.storyboard.root.baseTabBarController() { tabBarController.selectedIndex = 1 tabBarController.modalPresentationStyle = .fullScreen tabBarController.modalTransitionStyle = .crossDissolve self.baseTabBarController = tabBarController self.navigationController?.present(tabBarController, animated: true, completion: nil) } } 
Interesting Posts