Ios 模态视图控制器不覆盖状态栏
我正在开发一个ios应用程序。我有一个主视图,在这个视图中 我试图呈现一个背景暗淡的模式视图控制器(黑色,不透明度)。 问题是状态栏不受此颜色的影响,并且保持不变 以下是我演示视图控制器的方式:Ios 模态视图控制器不覆盖状态栏,ios,iphone,xcode,swift,Ios,Iphone,Xcode,Swift,我正在开发一个ios应用程序。我有一个主视图,在这个视图中 我试图呈现一个背景暗淡的模式视图控制器(黑色,不透明度)。 问题是状态栏不受此颜色的影响,并且保持不变 以下是我演示视图控制器的方式: let shareViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ShareViewController") as! ShareViewController shareViewC
let shareViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ShareViewController") as! ShareViewController
shareViewController.battle = battle
shareViewController.delegate = self
let animation = CATransition()
animation.duration = 1
animation.type = kCATransitionFade
self.view.window?.layer.addAnimation(animation, forKey: kCATransition)
presentViewController(shareViewController, animated: false) {
() in
// nothing here
}
以下是一些屏幕截图来演示问题:
这就是问题所在(状态栏颜色):
这是故事板中的模式视图:
当我用alpha!=1.呈现
UIViewController
类似:
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let destinationVC = storyBoard.instantiateViewController(withIdentifier: "AddComment") as! AddCommentViewController
destinationVC.modalPresentationStyle = .overCurrentContext //this line is important
destinationVC.delegate = self
destinationVC.restId = self.restaurant.id
self.present(destinationVC, animated: true, completion: nil)
然后在destinationVC
视图控制器中
override func viewWillDisappear(_: Bool) {
UIView.animate(withDuration: 1, animations: { () in
self.view.backgroundColor = .clear
})
super.viewWillDisappear(true)
}
override func viewWillAppear(_: Bool) {
UIView.animate(withDuration: 1, animations: { () in
self.view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
})
super.viewWillAppear(true)
}
并在
viewDidLoad
或故事板中将其backgroundColor
设置为。清除。因此,UIViewController
覆盖了包括状态栏在内的整个屏幕 您可以非常实用,只需在模态视图控制器启动时隐藏状态栏即可:
override func prefersStatusBarHidden() -> Bool {
return true
}
以下是您可能正在寻找的解决方案:
if let window = UIApplication.shared.keyWindow {
window.windowLevel = UIWindowLevelStatusBar + 1
}
这段代码的主要思想是,window
应用程序的窗口级别低于状态栏窗口级别。这段代码的作用是,只需将窗口的窗口级别设置为高于状态栏窗口级别,您的窗口就可以覆盖状态栏。别忘了,在显示视图控制器之前,必须在主线程上调用此代码。祝你好运 应使用执行自定义动画转换。以下是用于此目的的教程:
如果只需要淡入淡出动画,则可以通过更改要显示的viewController的ModAltTransitionStyle
属性来获得淡入淡出动画
尝试通过以下方式修复代码:
guard let shareViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ShareViewController") as! ShareViewController else {
//Fallback in case of nil?
return
}
shareViewController.modalTransitionStyle = .crossDissolve
presentViewController(shareViewController, animated: true, completion: nil)
另外请注意,presentViewController(shareViewController,动画:true,完成:nil)
适用于swift 2。等价的swift 3将出现(shareViewController,动画:true,完成:nil)
我无法重现您的问题,以下代码在我的单视图应用程序中正常工作:
let viewController = UIViewController()
viewController.modalPresentationStyle = .overFullScreen
viewController.view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
let animation = CATransition()
animation.duration = 1
animation.type = kCATransitionFade
self.view.window?.layer.add(animation, forKey: kCATransition)
self.present(viewController, animated: false, completion: nil)
但是请注意,您应该在视图的根控制器上显示。有时,当从内部控制器演示时,您可能会得到奇怪的效果:
self.view.window?.rootViewController?.present(viewController, animated: false, completion: nil)
还要确保您使用的是正确的modalPresentationStyle
您可以将此代码添加到查看Swift 3的控制器中:
let statusView: UIView = UIView(frame: CGRect(x: 0.0, y: -20.0, width: UIScreen.main.bounds.size.width, height: 20.0))
statusView.backgroundColor = UIColor.black
statusView.alpha = 0.8
self.addSubview(self.statusView)
将视图控制器设置为的根视图控制器,然后在级别上显示窗口
下面是一个Swift 3类,用于在所有其他UI元素(包括状态栏)上设置模式弹出窗口的动画。scrim视图用于对背景UI进行着色,并截取触摸以关闭视图
import UIKit
class ModalViewController: UIViewController {
private let scrimView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.black
view.alpha = 0.0
return view
}()
private var myWindow: UIWindow?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.clear
// Setup scrim View
view.addSubview(scrimView)
view.topAnchor.constraint(equalTo: scrimView.topAnchor).isActive = true
view.leftAnchor.constraint(equalTo: scrimView.leftAnchor).isActive = true
view.rightAnchor.constraint(equalTo: scrimView.rightAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: scrimView.bottomAnchor).isActive = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismiss as (Void) -> Void))
scrimView.addGestureRecognizer(tapGestureRecognizer)
// Layout custom popups or action sheets
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 0.25) {
self.scrimView.alpha = 0.5
// Animate in custom popups or action sheets
}
}
func present() {
myWindow = UIWindow(frame: UIScreen.main.bounds)
myWindow?.windowLevel = UIWindowLevelAlert
myWindow?.backgroundColor = UIColor.clear
myWindow?.rootViewController = self
myWindow?.isHidden = false
}
func dismiss() {
UIView.animate(
withDuration: 0.25,
animations: {
self.scrimView.alpha = 0.0
// Animate out custom popups or action sheets
},
completion: { success in
self.myWindow = nil
}
)
}
}
提出以下观点:
let modalView = ModalViewController()
modalView.present()
要取消该视图,请点击scrim上的任意位置。我假设这不是OP要查找的内容,不是隐藏状态栏,而是覆盖状态栏。不管怎么说,这可能是一个解决办法……我发现有一点是,寻求纯粹而美丽的解决方案是不值得的,因为苹果的SDK远不是纯粹而美丽的。事实上,如果它足够重要的话,你只需要超越你的限制,那么是的。请共享ShareViewController的代码,如果有任何这样做是相当危险的。通过更改键窗口的级别
可以在显示键盘(位于单独的窗口中)时获得非常奇怪的效果。此外,在解雇时,您必须恢复到原始级别。我建议创建一个与状态栏大小相同的新窗口,并将其放在状态栏的顶部,当控制器出现或消失时隐藏并显示它。正如我们所知,危险的事情不是公开的。我只是发布了能产生效果的解决方案,就像OP所要求的那样。当然,您的考虑是正确的,如果不小心使用此方法,可能会产生一些不必要的输出,但我可以反驳您对键盘的看法。无论如何,无意冒犯,你的解决方案看起来比这更好。我建议OP使用您的解决方案。如果采用这种方式,最好创建一个新窗口(而不是修改keyWindow)。另外,将windowLevel
设置为.alert
。