example ios swift statusbar modalviewcontroller in-call

ios - example - alamofire get



Problema de la barra de estado de llamadas entrantes de UIViewController (8)

Problema:

El controlador de vista presentado modalmente no retrocede una vez que desaparece la barra de estado durante la llamada, dejando un espacio vacío / transparente de 20 px en la parte superior.

Normal: sin problemas

En llamada: sin problemas

Después de que desaparezca la llamada:

Deja un espacio vacío / transparente de 20 px de alto en la parte superior que revela una vista naranja debajo. Sin embargo, la barra de estado todavía está presente sobre el área transparente. La barra de navegación también deja espacio para la barra de estado, solo tiene 20 píxeles de ubicación demasiado baja.

  • basado en iOS 10
  • Controlador de vista presentado modalmente
  • Presentación modal personalizada
  • El controlador de vista principal detrás es naranja
  • No usar Autolayout
  • Cuando se gira a horizontal , la barra de llamadas entrantes de 20 píxeles deja y aún deja un espacio de 20 píxeles.
  • Opto por no mostrar la barra de estado en orientaciones horizontales. (es decir, la mayoría de las aplicaciones de stock)

Traté de escuchar a los delegados de la aplicación:

willChangeStatusBarFrame didChangeStatusBarFrame

Ver también las notificaciones basadas en el controlador:

UIApplicationWillChangeStatusBarFrame UIApplicationDidChangeStatusBarFrame

Cuando registro el marco de la vista presentada para los cuatro métodos anteriores, el marco siempre está en el origen (y: 0).

Actualizar

Ver presentación modal personalizada del controlador

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


Asegúrese de establecer el marco de la vista del controlador de vista que está presentando en los límites de la vista del contenedor, después de que se haya agregado a la vista del contenedor. Esto resolvió el problema para mí.

containerView.addSubview(toViewController.view) toViewController.view.frame = containerView.bounds


Creo que esto es un error en UIKit. El containerView que contiene la vista de un controlador presentado que se presentó utilizando una transición personalizada no parece retroceder por completo cuando la barra de estado vuelve al tamaño normal. (Puede verificar la jerarquía de la vista después de cerrar la barra de estado de la llamada)

Para resolverlo, puede proporcionar un controlador de presentación personalizado al presentar. Y luego, si no necesita que la vista del controlador de presentación permanezca en la jerarquía de vistas, puede devolver true para la propiedad shouldRemovePresentersView del controlador de presentación, y eso es todo.

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

o si necesita que la vista del controlador actual permanezca, puede observar el cambio en el marco de la barra de estado y ajustar manualmente containerView para que tenga el mismo tamaño que su supervista

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


En mi caso, estoy usando un estilo de presentación personalizado para mi ViewController. El problema es que la posición Y no se calcula bien. Digamos que la altura de la pantalla original es de 736p. Intente imprimir view.frame.origin.y y view.frame.height , encontrará que la altura es 716p y la y es 20. Pero la altura de la pantalla es 736 - 20 (altura adicional de la barra de estado en llamada) 20 (posición y). Es por eso que nuestra vista se corta desde la parte inferior del ViewController y por qué hay un margen de 20p en la parte superior. Pero si regresa para ver el valor de cuadro del controlador de navegación. Descubrirá que no importa si se muestra o no la barra de estado durante la llamada, la posición y siempre es 0.

Entonces, todo lo que tenemos que hacer es establecer la posición y en cero.

override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let f = self.view.frame if f.origin.y != 0 { self.view.frame = CGRect(x: f.origin.x, y: 0, width: f.width, height: f.height) self.view.layoutIfNeeded() self.view.updateConstraintsIfNeeded() } }


He estado buscando una solución a este problema. De hecho, publiqué una nueva pregunta similar a esta. Aquí: ¿Cómo evitar la barra de navegación de ubicación azul de iOS?

Créame, he estado resolviendo esto durante un par de días y es realmente molesto tener su pantalla en mal estado debido a los cambios en la barra de estado del iOS por llamada entrante, punto de acceso y ubicación.

Intenté implementar la respuesta de Modi, puse ese fragmento de código en mi AppDelegate y lo modifiqué un poco, pero no tuve suerte. y creo que iOS lo hace automáticamente para que no tenga que implementarlo usted mismo.

Antes de descubrir al culpable del problema, probé cada solución en esta pregunta en particular. No es necesario implementar el método de AppDelegate willChangeStatusBar... o agregar una notificación para observar los cambios de statusBar.

También rehice algunos de los flujos de mi proyecto, haciendo algunas pantallas mediante programación (estoy usando guiones gráficos). Y experimenté un poco, luego inspeccioné mis proyectos anteriores y otros actuales por qué están haciendo el ajuste correctamente :)

La conclusión es : estoy presentando mi pantalla principal con UITabBarController de manera incorrecta.

Siempre tenga en cuenta el modalPresentationStyle . Tuve la idea de revisar mi código debido al comentario de Noah.

Muestra:

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


He estado buscando una solución durante 3 días. No me gusta esta solución, pero no encontré una mejor manera de solucionarla.

Tengo una situación en la que la vista rootViewController tiene una altura mayor para 20 puntos que la ventana, cuando recibo una notificación sobre las actualizaciones de altura de la barra de estado, configuro manualmente el valor correcto.

Agregar método a AppDelegate.swift

func application(_ application: UIApplication, didChangeStatusBarFrame oldStatusBarFrame: CGRect) { if let window = application.keyWindow { window.rootViewController?.view.frame = window.frame } }

Después de eso funciona como se esperaba (incluso después de los cambios de orientación). Espero que ayude a alguien, porque pasé demasiado tiempo en esto.

PD: Parpadea un poco, pero funciona.


Resuelvo este problema usando una línea de código

En el objetivo C

tabBar.autoresizingMask = (UIViewAutoResizingFlexibleWidth | UIViewAutoResizingFlexibleTopMargin);

En veloz

self.tabBarController?.tabBar.autoresizingMask = UIViewAutoresizing(rawValue: UIViewAutoresizing.RawValue(UInt8(UIViewAutoresizing.flexibleWidth.rawValue) | UInt8(UIViewAutoresizing.flexibleTopMargin.rawValue)))`

Solo tiene que hacer que autoresizingMask de tabBar sea flexible desde la parte superior.


También enfrenté este problema, pero después de poner este método, el problema desapareció.

iOS tiene su método predeterminado willChangeStatusBarFrame para manejar la barra de estado. Por favor, ponga este método y verifíquelo.

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

Espero que esto te ayude.
Gracias


Tuve el mismo problema con el hospot personal modificando la barra de estado. La solución es registrarse en la notificación del sistema para el cambio del marco de la barra de estado, esto le permitirá actualizar su diseño y debería solucionar cualquier problema de diseño que pueda tener. Mi solución que debería funcionar exactamente igual para usted es esta:

  • En su controlador de vista, en viewWillAppear a la UIApplicationDidChangeStatusBarFrameNotification

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(myControllerName.handleFrameResize(_:)), name: UIApplicationDidChangeStatusBarFrameNotification, object: nil)

  • Crea tu método selector

    func handleFrameResize(notification: NSNotification) { self.view.layoutIfNeeded() }

  • Retire su controlador del centro de notificaciones en viewWillDisappear

    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationDidChangeStatusBarFrameNotification, object: nil)

  • También necesita su modal para estar a cargo de la barra de estado, por lo que debe configurar

    destVC.modalPresentationCapturesStatusBarAppearance = true antes de presentar la vista.

Puede implementar esto en cada controlador susceptible de tener un cambio en la barra de estado, o puede hacer otra clase que lo haga para cada controlador, como pasar a un método, mantener la referencia para cambiar el diseño y tener un método quitarse a uno mismo. Ya sabes, para reutilizar el código.