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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 08:33:34  来源:igfitidea点击:

Modal view controller does not cover status bar

iosiphonexcodeswift

提问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.

Example

例子

回答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 UIViewControllerwith alpha != 1. present UIViewControllerlike:

这段代码对我有用,当我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 destinationVCview 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 backgroundColorto .clearin viewDidLoador storyboard. So UIViewControllercovers whole screen including status bar.

并将其设置backgroundColor.clearinviewDidLoad或 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, windowof 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 modalTransitionStyleproperty 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
}