Problème:
Le contrôleur de vue présenté de façon modale ne remonte pas après la disparition de la barre d'état en cours d'appel, laissant un espace vide/transparent de 20 pixels en haut.
Normal: Aucun problème
En appel: aucun problème
Après la disparition de l'appel en cours:
Laisse un espace vide/transparent de 20 pixels de haut en haut, laissant apparaître la vue orange ci-dessous. Cependant, la barre d'état est toujours présente sur la zone transparente. La barre de navigation laisse également de la place pour la barre d’état, son placement n’est que de 20 pixels.
J'ai essayé d'écouter les délégués de l'application:
willChangeStatusBarFrame
didChangeStatusBarFrame
Afficher également les notifications basées sur le contrôleur:
UIApplicationWillChangeStatusBarFrame
UIApplicationDidChangeStatusBarFrame
Lorsque je consigne le cadre de la vue présentée pour les quatre méthodes ci-dessus, le cadre est toujours à (y: 0) Origine.
View Controller Présentation modale personnalisée
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)
})
}
J'ai fait face à ce problème aussi mais après avoir mis cette méthode, le problème est parti.
iOS a sa méthode par défaut willChangeStatusBarFrame
pour gérer la barre d'état. S'il vous plaît mettez cette méthode et vérifiez-la.
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
})
}
J'espère que cette chose va vous aider.
Je vous remercie
Je cherche une solution depuis 3 jours. Je n'aime pas cette solution mais je n'ai pas trouvé de meilleur moyen de la réparer.
Il y a une situation où la vue rootViewController a une hauteur supérieure de 20 points à celle de la fenêtre. Lorsque j'ai une notification concernant les mises à jour de la hauteur de la barre d'état, je configure manuellement la valeur correcte.
Ajouter une méthode à la AppDelegate.Swift
func application(_ application: UIApplication, didChangeStatusBarFrame oldStatusBarFrame: CGRect) {
if let window = application.keyWindow {
window.rootViewController?.view.frame = window.frame
}
}
Après cela, cela fonctionne comme prévu (même après les changements d’orientation) ... Je pense que ça va aider quelqu'un, parce que j’ai passé trop de temps là-dessus.
P.S. Il clignote un peu, mais fonctionne.
Je pense que c'est un bug dans UIKit. La containerView
qui contient la vue d'un contrôleur présenté qui a été présentée à l'aide d'une transition personnalisée ne semble pas revenir complètement lorsque la barre d'état a retrouvé sa taille normale. (Vous pouvez vérifier la hiérarchie des vues après avoir fermé la barre d'état de l'appel)
Pour le résoudre, vous pouvez fournir un contrôleur de présentation personnalisé lors de la présentation. Et puis, si vous n'avez pas besoin que la vue du contrôleur présentateur reste dans la hiérarchie des vues, vous pouvez simplement renvoyer la propriété true
pour shouldRemovePresentersView
du contrôleur de présentation, et c'est tout.
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
}
}
ou si vous souhaitez que la vue du contrôleur présentateur soit conservée, vous pouvez observer le changement de cadre de la barre d'état et ajuster manuellement la variable containerView
pour qu'elle ait la même taille que sa vue d'ensemble.
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
})
}
}
}
J'ai eu le même problème avec l'hospot personnel qui modifiait la barre d'état .. La solution consiste à s'inscrire à la notification système pour le changement de cadre de la barre d'état, cela vous permettra de mettre à jour votre mise en page et de corriger tout problème de mise en page que vous pourriez rencontrer as . Ma solution qui devrait fonctionner exactement de la même manière pour vous est la suivante:
Dans votre contrôleur de vue, dans viewWillAppear
, abonnez-vous à la UIApplicationDidChangeStatusBarFrameNotification
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(myControllerName.handleFrameResize(_:)), name: UIApplicationDidChangeStatusBarFrameNotification, object: nil)
Créez votre méthode de sélection
func handleFrameResize(notification: NSNotification) {
self.view.layoutIfNeeded() }
Supprimez votre contrôleur du centre de notification dans viewWillDisappear
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationDidChangeStatusBarFrameNotification, object: nil)
Vous avez également besoin que votre modal soit en charge de la barre d'état, vous devez donc définir
destVC.modalPresentationCapturesStatusBarAppearance = true
avant de présenter la vue.
Vous pouvez soit implémenter cela sur chaque contrôleur susceptible de modifier la barre d'état, soit créer une autre classe qui le fera pour chaque contrôleur, par exemple, passer à une méthode, conserver la référence pour modifier la présentation et disposer d'une méthode. se retirer. Vous savez, afin de réutiliser le code.
Je cherchais une solution à ce problème. En fait, j'ai posté une nouvelle question semblable à celle-ci. Ici: Comment éviter la barre de navigation d'emplacement bleu iOS Messing Up My StatusBar?
Croyez-moi, je résous ce problème depuis quelques jours maintenant et il est vraiment agaçant de perdre votre écran en raison des modifications apportées à la barre d'état d'iOS par appel entrant, point d'accès sans fil et emplacement.
J'ai essayé d'implémenter la réponse de Modi, j'ai mis ce morceau de code dans mon AppDelegate et l'ai légèrement modifié, mais pas de chance. et je crois que iOS le fait automatiquement afin que vous n'ayez pas à l'implémenter vous-même.
Avant de découvrir le coupable du problème, j'ai essayé toutes les solutions à cette question particulière. Pas besoin d'implémenter la méthode Appcode Code willChangeStatusBar...
ou d'ajouter une notification pour observer les changements de statusBar.
J'ai également refait certains des flux de mon projet, en effectuant des écrans par programmation (j'utilise des story-boards). Et j’ai expérimenté un peu, puis j’ai inspecté mes précédents et d’autres projets en cours pour savoir pourquoi ils faisaient les ajustements correctement :)
Bottom line is: Je présente mon écran principal avec UITabBarController de manière si erronée.
Veuillez toujours prendre note de la modalPresentationStyle
. J'ai eu l'idée de vérifier mon code à cause du commentaire de Noah.
Échantillon:
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)
}
}
Je résous ce problème en utilisant une ligne de code
En Objectif C
tabBar.autoresizingMask = (UIViewAutoResizingFlexibleWidth | UIViewAutoResizingFlexibleTopMargin);
En rapide
self.tabBarController?.tabBar.autoresizingMask =
UIViewAutoresizing(rawValue: UIViewAutoresizing.RawValue(UInt8(UIViewAutoresizing.flexibleWidth.rawValue) | UInt8(UIViewAutoresizing.flexibleTopMargin.rawValue)))`
Il vous suffit de rendre autoresizingMask de tabBar flexible en partant du haut.
Veillez à définir le cadre de la vue du contrôleur de vue que vous présentez sur les limites de la vue du conteneur, après l'avoir ajouté à la vue du conteneur. Cela a résolu le problème pour moi.
containerView.addSubview(toViewController.view)
toViewController.view.frame = containerView.bounds