xcode 模态视图控制器不覆盖状态栏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35491746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Modal view controller does not cover status bar
提问by Eden.F
I'm developing an ios app. I have a a main view and in this view im trying to present a modal view controller with dimmed background(black with opacity). The problem is that the status bar is not affected by this color and remains the same.
我正在开发一个 ios 应用程序。我有一个主视图,在这个视图中我试图呈现一个背景变暗的模态视图控制器(黑色不透明度)。问题是状态栏不受这种颜色的影响,保持不变。
This is how i present the view controller:
这就是我展示视图控制器的方式:
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
}
Here are some screenshots to demonstrate the problem:
以下是一些屏幕截图来演示问题:
This is the problem(status bar color): Problem illustrationThis is the modal view in storyboard: storyboard
回答by Sulthan
I cannot reproduce your problem, the following code works without problems in my single view app:
我无法重现您的问题,以下代码在我的单视图应用程序中没有问题:
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)
However note that you should be presenting over the root controller of the view. Sometimes you can get strange effects when presenting from your internal controllers:
但是请注意,您应该在视图的根控制器上呈现。有时,从内部控制器呈现时会得到奇怪的效果:
self.view.window?.rootViewController?.present(viewController, animated: false, completion: nil)
Also make sure you are using the correct modalPresentationStyle
.
还要确保您使用的是正确的modalPresentationStyle
.
回答by Alex Givens
Set your view controller as the root view controller of a UIWindow, then present the window at the UIWindowLevelAlertlevel.
将您的视图控制器设置为UIWindow的根视图控制器,然后在UIWindowLevelAlert级别显示窗口。
Below is a Swift 3class used to animate a modal popup over all other UI elements, including the status bar. A scrim view is used to shade background UI and intercept touches to dismiss the view.
下面是一个Swift 3类,用于为所有其他 UI 元素(包括状态栏)上的模式弹出窗口设置动画。纱布视图用于为背景 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
}
)
}
}
To present the view:
要呈现视图:
let modalView = ModalViewController()
modalView.present()
To dismiss the view, tap anywhere on the scrim.
要关闭视图,请点击稀松布上的任意位置。
回答by Ali ZahediGol
you can add this code to view controller for Swift 3:
您可以将此代码添加到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)
回答by JuicyFruit
this code works for me, when I am presenting UIViewController
with alpha != 1. present UIViewController
like:
这段代码对我有用,当我UIViewController
用 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)
then in destinationVC
view controller
然后在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)
}
and set its backgroundColor
to .clear
in viewDidLoad
or storyboard. So UIViewController
covers whole screen including status bar.
并将其设置backgroundColor
为.clear
inviewDidLoad
或 storyboard。所以UIViewController
覆盖整个屏幕,包括状态栏。
回答by Fahri Azimov
Here is the solution you might be looking for:
这是您可能正在寻找的解决方案:
if let window = UIApplication.shared.keyWindow {
window.windowLevel = UIWindowLevelStatusBar + 1
}
The main idea behind this code is, window
of your application has a window level which is lower than status bar window level. And what this code does is, just put your window's window level higher than status bar window level, and your window can now cover the status bar. Don't forget, this code has to be called on main thread, just before presenting your view controller. Good luck!
此代码背后的主要思想是,window
您的应用程序的窗口级别低于状态栏窗口级别。而这段代码的作用是,只要把你的窗口的窗口级别高于状态栏的窗口级别,你的窗口现在就可以覆盖状态栏了。不要忘记,必须在主线程上调用此代码,就在呈现您的视图控制器之前。祝你好运!
回答by Giuseppe Lanza
Custom animation transitions should be performed using UIViewControllerAnimatedTransitioning. Here is a tutorial for this purpose: https://www.raywenderlich.com/110536/custom-uiviewcontroller-transitions
应该使用UIViewControllerAnimatedTransitioning执行自定义动画过渡。这是为此目的的教程:https: //www.raywenderlich.com/110536/custom-uiviewcontroller-transitions
If all you want is a fade animation you can have it by changing the modalTransitionStyle
property of the viewController you are going to display.
如果您想要的只是淡入淡出动画,则可以通过更改modalTransitionStyle
要显示的 viewController的属性来实现。
Try by fixing your code this way:
尝试以这种方式修复您的代码:
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)
Also please note that presentViewController(shareViewController, animated: true, completion: nil)
is for swift 2. The equivalent swift 3 would be present(shareViewController, animated: true, completion: nil)
另请注意,这presentViewController(shareViewController, animated: true, completion: nil)
是针对 swift 2 的。等效的 swift 3 将是present(shareViewController, animated: true, completion: nil)
回答by ClayJ
You could be extremely practical and simply hide the status bar when your modal view controller is up:
您可以非常实用,只需在模态视图控制器启动时隐藏状态栏:
override func prefersStatusBarHidden() -> Bool {
return true
}