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) } }