Модальный контроллер просмотра не закрывает строку состояния

Я разрабатываю приложение ios. У меня есть главный взгляд и в этом представлении im пытается представить модальный контроллер просмотра с затемненным фоном (черный с непрозрачностью). Проблема в том, что этот индикатор не влияет на строку состояния.

Вот как я представляю контроллер вида:

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
            }

Вот несколько скриншотов, чтобы продемонстрировать проблему:

Это проблема (цвет строки состояния): Иллюстрация проблемы Это модальный вид в раскадровке: раскадровка

Ответ 1

Я не могу воспроизвести вашу проблему, следующий код работает без проблем в моем приложении с одним представлением:

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.

Пример

Ответ 2

этот код работает для меня, когда я представляю UIViewController с альфа!= 1. present UIViewController like:

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

и установите его backgroundColor на .clear в viewDidLoad или раскадровку. Таким образом, UIViewController охватывает весь экран, включая строку состояния.

Ответ 3

Вы можете быть очень практичным и просто скрыть строку состояния, когда ваш контроллер модального просмотра вверх:

    override func prefersStatusBarHidden() -> Bool {
    return true
}

Ответ 4

Вот решение, которое вы можете искать:

if let window = UIApplication.shared.keyWindow {
   window.windowLevel = UIWindowLevelStatusBar + 1
}

Основная идея этого кода: window вашего приложения имеет уровень окна, который ниже уровня окна строки состояния. И что делает этот код, просто оставьте уровень окна окна выше уровня окна состояния, и теперь ваше окно может теперь закрывать строку состояния. Не забывайте, что этот код нужно вызвать в основном потоке, перед представлением вашего контроллера вида. Удачи!

Ответ 5

Пользовательские переходы анимации должны выполняться с помощью UIViewControllerAnimatedTransitioning. Вот вам учебник для этой цели: https://www.raywenderlich.com/110536/custom-uiviewcontroller-transitions

Если все, что вам нужно, это анимация затухания, вы можете получить ее, изменив свойство modalTransitionStyle viewController, которое вы собираетесь отображать.

Попробуйте установить код таким образом:

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, animated: true, completion: nil) для Swift 2. Эквивалентный swift 3 будет present(shareViewController, animated: true, completion: nil)

Ответ 6

вы можете добавить этот код для просмотра контроллера для 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)

Ответ 7

Установите контроллер вида в качестве контроллера корневого представления UIWindow, затем укажите окно в UIWindowLevelAlert.

Ниже приведен класс Swift 3, используемый для анимации модального всплывающего окна по всем другим элементам пользовательского интерфейса, включая строку состояния. Скрытый вид используется для затенения фонового интерфейса и перехвата штрихов, чтобы закрыть представление.

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

Чтобы отклонить представление, нажмите в любом месте на экране.