Ios UIViewController在调用状态栏中出现问题
问题: Modally presented view controller在调用状态栏消失后不会向上移动,在顶部留下20px的空白/透明空间Ios UIViewController在调用状态栏中出现问题,ios,swift,statusbar,modalviewcontroller,in-call,Ios,Swift,Statusbar,Modalviewcontroller,In Call,问题: Modally presented view controller在调用状态栏消失后不会向上移动,在顶部留下20px的空白/透明空间 正常:无问题 通话中:无问题 呼叫消失后: 在顶部留下一个20px高的空白/透明空间,下面显示橙色视图。但是,状态栏仍然存在于透明区域上。导航栏也为状态栏留出了空间,因为它的位置太低,只有20px 基于iOS 10的 模态显示视图控制器 自定义模态表示法 后面的主视图控制器是橙色的 不使用自动布局 当旋转到横向时,调用栏中的20px会离开
正常:无问题
通话中:无问题
呼叫消失后: 在顶部留下一个20px高的空白/透明空间,下面显示橙色视图。但是,状态栏仍然存在于透明区域上。导航栏也为状态栏留出了空间,因为它的位置太低,只有20px
- 基于iOS 10的
- 模态显示视图控制器
- 自定义模态表示法
- 后面的主视图控制器是橙色的
- 不使用自动布局
- 当旋转到横向时,调用栏中的20px会离开,并且仍然会留下20px的间隙
- 我选择退出横向显示状态栏。(即大多数股票应用程序)
willChangeStatusBarFrame
didChangeStatusBarFrame
还可以查看基于控制器的通知:
UIApplicationWillChangeStatusBarFrame
UIApplicationDidChangeStatusBarFrame
当我为上述四种方法记录显示视图的帧时,该帧始终位于(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)
})
}
我也面临着这个问题,但在我采用这种方法之后,问题就消失了 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
})
}
希望这件事对你有帮助。
谢谢我对人事经理修改状态栏也有同样的问题。 解决方案是注册到系统通知以更改状态栏框架,这将允许您更新布局,并应修复可能存在的任何布局问题。 我的解决方案应该与您的解决方案完全相同:
- 在视图控制器中,在
视图中将出现
中的
引用
UIApplicationIDChangeStatusBarFrameNotification
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(myControllerName.handleFrameResize(_:)), name: UIApplicationDidChangeStatusBarFrameNotification, object: nil)
- 创建选择器方法
func handleFrameResize(notification: NSNotification) { self.view.layoutIfNeeded() }
- 从
视图中的通知中心删除控制器将消失
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationDidChangeStatusBarFrameNotification, object: nil)
- 您还需要您的模态来负责状态栏,因此您应该设置
在陈述观点之前destVC.modalPresentationCapturesStatusBarAppearance=true
您可以在状态栏上容易发生更改的每个控制器上实现此功能,也可以创建另一个类来为每个控制器实现此功能,例如将self传递给一个方法,保留引用以更改布局,并使用一个方法删除self。你知道,为了重用代码。我认为这是UIKit中的一个bug。当状态栏恢复到正常大小时,包含使用自定义转换显示的控制器视图的
containerView
似乎不会完全向后移动。(您可以在关闭in call状态栏后检查视图层次结构)
要解决此问题,您可以在演示时提供自定义演示控制器。然后,如果您不需要演示控制器的视图保留在视图层次结构中,您只需返回演示控制器的true
forshouldRemovePresenterView
属性即可
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
使其与superview的大小相同
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
})
}
}
}
类PresentationController:UIPresentationController{
重写初始化(presentedViewController:UIViewController,presentingViewController:UIViewController?){
super.init(presentedViewController:presentedViewController,presenting:presentingViewController)
NotificationCenter.default.addObserver(self,
选择器:#选择器(self.onStatusBarChanged),
名称:.UIApplicationWillChangeStatusBarFrame,
对象:无)
}
@objc func onStatusBarChanged(注:NSNotification){
//我找不到办法向系统询问这些常数的值,也许你可以
如果UIApplication.shared.statusBarFrame.height我一直在寻找这个问题的解决方案。事实上,我发布了一个与此类似的新问题。这里:
相信我,我已经解决这个问题好几天了,由于iOS的状态栏在通话、热点和位置上的变化,你的屏幕被弄乱了,这真的很烦人
我已经尝试过实现莫迪的答案,我把这段代码放在AppDelegate中,并对其进行了一些修改,但运气不好。我相信iOS会自动实现这一点,所以你不必自己实现
在我发现问题的原因之前,我尝试了这个特定问题的所有解决方案。无需实现AppDelegate的方法willChangeStatusBar…
或添加通知来观察状态栏的更改
我还通过编程方式重做了一些屏幕(我使用的是故事板),重做了我项目的一些流程。我做了一些实验,然后检查了我以前和当前的其他项目,为什么他们能正确地进行调整:)
底线是:我用UITabBarController以错误的方式显示我的主屏幕
请始终注意modalPresentationStyle
。由于Noah的评论,我想查看我的代码
样本:
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)
}
}
我已经找了3天的解决方案。我不喜欢这个解决方案,但没有找到更好的方法来解决它
当rootViewController视图的高度比window高20点时,当我收到状态栏高度更新的通知时,我手动设置正确的值
将方法添加到AppDelegate.sw
func application(_ application: UIApplication, didChangeStatusBarFrame oldStatusBarFrame: CGRect) {
if let window = application.keyWindow {
window.rootViewController?.view.frame = window.frame
}
}
tabBar.autoresizingMask = (UIViewAutoResizingFlexibleWidth | UIViewAutoResizingFlexibleTopMargin);
self.tabBarController?.tabBar.autoresizingMask =
UIViewAutoresizing(rawValue: UIViewAutoresizing.RawValue(UInt8(UIViewAutoresizing.flexibleWidth.rawValue) | UInt8(UIViewAutoresizing.flexibleTopMargin.rawValue)))`
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let f = self.view.frame
if f.origin.y != 0 {
self.view.frame = CGRect(x: f.origin.x, y: 0, width: f.width, height: f.height)
self.view.layoutIfNeeded()
self.view.updateConstraintsIfNeeded()
}
}