iOS 7: UITableView se muestra en la barra de estado

La primera pantalla de mi aplicación es un UITableViewController sin una barra de navegación, lo que significa que el contenido fluye bajo la barra de estado por lo que hay una gran cantidad de colisiones de texto. Ajusté tanto las propiedades de Under top bars como las de Adjust scroll view insets que realmente impiden que se desplace por debajo, pero a costa de mantener baja la parte superior de la vista de tabla. UITableView configurar el marco de UITableView en 20 píxeles, pero parece que no surte efecto y, como actualmente necesito que la aplicación sea compatible con iOS 6, no puedo saltar a los storyboards de iOS 7 para forzar el autolayout. usa la guía de altura superior. ¿Alguien ha encontrado una solución que funcione para ambas versiones?

Cosas que he intentado: establecer edgesForExtendedLayout , cambiar las configuraciones en Storyboard para Under top bars y Adjust scroll view , forzando el marco a una nueva área.

Una imagen vale mas que mil palabras: Flujo de la barra de estado bajo

Para cualquier persona interesada en replicar esto, simplemente siga estos pasos:

  1. Crea un nuevo proyecto de iOS
  2. Abra el guión gráfico principal y elimine el UIViewController predeterminado / inicial
  3. Arrastra un nuevo UITableViewController desde la Biblioteca de objetos
  4. Establecerlo como el controlador de vista inicial
  5. Alimente la tabla con algunos datos de prueba

Si sigue los pasos anteriores, cuando ejecute la aplicación, verá que nada, incluido el ajuste de las casillas de Xcode para “Extender bordes en las barras ‘Arriba, Abajo, opacas’, funciona para evitar que la primera fila aparezca debajo de la barra de estado. ni puede abordar esto programáticamente.

Por ejemplo, en el escenario anterior, lo siguiente no tendrá ningún efecto:

 // These do not work self.edgesForExtendedLayout=UIRectEdgeNone; self.extendedLayoutIncludesOpaqueBars=NO; self.automaticallyAdjustsScrollViewInsets=NO; 

Este problema puede ser muy frustrante, y creo que es un error al final de Apple, especialmente porque se muestra en su propio UITableViewController precableado de la biblioteca de objetos.

No estoy de acuerdo con todos los que están tratando de resolver esto mediante el uso de cualquier forma de “Números mágicos”, por ejemplo, “usar un delta de 20px”. Este tipo de progtwigción estrechamente acoplada definitivamente no es lo que Apple quiere que hagamos aquí.

He descubierto dos soluciones a este problema:

  • Preservar la escena de UITableViewController :
    Si desea mantener el UITableViewController en el guión gráfico, sin colocarlo manualmente en otra vista, puede incrustar el UITableViewController en un UINavigationController (Editor> Incrustar en> Controlador de navegación) y desmarcar “Muestra la barra de navegación” en el inspector. Esto resuelve el problema sin necesidad de ajustes adicionales, y también preserva la escena de UITableViewController en el guión gráfico.

  • Uso de AutoLayout e incrustación de UITableView en otra vista (creo que así es como Apple quiere que hagamos esto) :
    Cree un UIViewController vacío y arrastre su UITableView en él. Luego, UITableView Ctrl y arrastre desde su UITableView hacia la barra de estado. Cuando el mouse llegue a la parte inferior de la barra de estado, verá una burbuja de ajuste automático que dice “Guía de diseño superior”. Suelte el mouse y elija “Espaciado vertical”. Eso le dirá al sistema de diseño que lo coloque justo debajo de la barra de estado.

He probado ambas formas en una aplicación vacía y ambas funcionan. Es posible que deba hacer algunos ajustes adicionales para que funcionen para su proyecto.

Si está haciendo cosas programáticamente y está utilizando un UITableViewController sin un UINavigationController su mejor UINavigationController es hacer lo siguiente en viewDidLoad :

Swift 3

 self.tableView.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0) 

Swift anterior

 self.tableView.contentInset = UIEdgeInsetsMake(20.0f, 0.0f, 0.0f, 0.0f); 

El UITableViewController seguirá UITableViewController detrás de la barra de estado, pero no estará debajo cuando se desplaza hacia la parte superior.

Tenga en cuenta: Esto funcionó para mí para la siguiente configuración:

  • Sin barra de navegación en la parte superior de la pantalla (la vista de tabla se encuentra con la barra de estado)
  • La vista de tabla no es desplazable

Si no se cumplen los dos requisitos anteriores, su kilometraje puede variar.

Publicación original

Creé mi vista programáticamente y esto terminó trabajando para mí:

 - (void) viewDidLayoutSubviews { // only works for iOS 7+ if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { CGRect viewBounds = self.view.bounds; CGFloat topBarOffset = self.topLayoutGuide.length; // snaps the view under the status bar (iOS 6 style) viewBounds.origin.y = topBarOffset * -1; // shrink the bounds of your view to compensate for the offset viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1); self.view.bounds = viewBounds; } } 

Fuente (en la sección superiorLayoutGuide en la parte inferior de la página 39).

Agregando a la respuesta superior:

después de que el segundo método no pareció funcionar, realicé algunas modificaciones adicionales y encontré la solución.

TLDR; la segunda solución de la respuesta superior casi funciona, pero para algunas versiones de xCode ctrl + arrastrando a “Top Layout Guide” y seleccionando Vertical Spacing no hace nada. Sin embargo, primero ajustando el tamaño de la Vista de tabla y luego seleccionando “Guía de distribución de espacio superior a superior” funciona


  1. Arrastre un ViewController en blanco al guión gráfico. Ver controlador

  2. Arrastre un objeto UITableView a la Vista. (No UITableViewController). Colóquelo en el centro utilizando las guías de diseño azules.

Vista de tablaImagen central

  1. Arrastre una UITableViewCell dentro de TableView. Esta será su celda de reutilización de prototipo, así que no olvide configurar su Reutilización de identificador en la pestaña Atributos o obtendrá un locking.

Agregar celda de vista de tablaIdentificador de reutilización

  1. Cree su subclase personalizada de UIViewController y agregue los . No olvides configurar ViewController de tu guión gráfico en esta clase en el Inspector de identidad.

  2. Cree una salida para su TableView en su archivo de implementación y asígnele el nombre “tableView”

Crear OutlettableView

  1. Haga clic con el botón derecho en TableView y arrastre tanto el dataSource como el delegado a su ViewController.

delegado de dataSource

Ahora, por la parte de no cortar en la barra de estado.

  1. Agarra el borde superior de tu vista de tabla y muévela hacia abajo a una de las guías azules de diseño automático que están cerca de la parte superior

redimensionar

  1. Ahora, puede controlar el arrastre desde la Vista de tabla a la parte superior y seleccionar el espacio superior a la guía de diseño superior

Guía de diseño Top Space to Top

  1. Le dará un error sobre el diseño ambiguo de TableView, solo agregue las restricciones faltantes y su finalización.

Agregar restricciones faltantes

¡Ahora puede configurar su vista de tabla como lo hace normalmente y no recortará la barra de estado!

 - (void) viewDidLayoutSubviews { if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) { self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque; if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone; // iOS 7 specific CGRect viewBounds = self.view.bounds; CGFloat topBarOffset = self.topLayoutGuide.length; viewBounds.origin.y = topBarOffset * -1; self.view.bounds = viewBounds; self.navigationController.navigationBar.translucent = NO; } } 

https://developer.apple.com/library/ios/documentation/userexperience/conceptual/TransitionGuide/SupportingEarlieriOS.html#//apple_ref/doc/uid/TP40013174-CH14-SW1

Así es como escribirlo en “Swift” Un ajuste a la respuesta de @lipka:

 tableView.contentInset = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0) 

Seleccione UIViewController en su guión gráfico y desmarque la opción Extender bordes debajo de las barras superiores. Trabajó para mi. 🙂

Para Xcode 7, la marca de verificación ‘translúcida’ para la barra de navegación funcionó para mí.

enter image description here

Esto lo arreglará para un UITableViewController (sin ningún número mágico). Lo único que no pude solucionar fue si está atendiendo una llamada telefónica, en cuyo caso la parte superior de la mesa se presiona demasiado. Si alguien sabe cómo resolver eso, háganoslo saber.

 class MyTableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() configureTableViewTop() } override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) coordinator.animateAlongsideTransition({ (context) -> Void in }, completion: { (context) -> Void in self.configureTableViewTop() }) } func configureTableViewTop() { tableView.contentInset.top = UIApplication.sharedApplication().statusBarFrame.height } } 

No sé qué tan Kosher es, pero descubrí que este esquema mueve la vista de ViewController y proporciona a la barra de estado un fondo sólido:

 - (void)viewDidLoad { [super viewDidLoad]; // Shove everything down if iOS 7 or later float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; if (systemVersion >= 7.0f) { // Move the view down 20 pixels CGRect bounds = self.view.bounds; bounds.origin.y -= 20.0; [self.view setBounds:bounds]; // Create a solid color background for the status bar CGRect statusFrame = CGRectMake(0.0, -20.0, bounds.size.width, 20); UIView* statusBar = [[UIView alloc] initWithFrame:statusFrame]; statusBar.backgroundColor = [UIColor redColor]; [self.view addSubview:statusBar]; } 

Por supuesto, reemplace redColor con el color que desee para el fondo.

Debe hacer uno de los swizzles por separado para establecer el color de los caracteres / símbolos en la barra de estado. Uso la View controller-based status bar appearance = NO y el Status bar style = Opaque black style en el plist, para hacer esto globalmente.

Parece que funciona, y me gustaría saber si hay errores o problemas con él.

La respuesta de chappjc funciona muy bien cuando se trabaja con XIB.

Encontré que la solución más limpia cuando se crea TableViewControllers programáticamente es envolviendo la instancia de UITableViewController en otro UIViewController y configurando las restricciones en consecuencia.

Aquí está:

 UIViewController *containerLeftViewController = [[UIViewController alloc] init]; UITableViewController *tableViewController = [[UITableViewController alloc] init]; containerLeftViewController.view.backgroundColor = [UIColor redColor]; hostsAndMoreTableViewController.view.translatesAutoresizingMaskIntoConstraints = NO; [containerLeftViewController.view addSubview:tableViewController.view]; [containerLeftViewController addChildViewController:tableViewController]; [tableViewController didMoveToParentViewController:containerLeftViewController]; NSDictionary * viewsDict = @{ @"tableView": tableViewController.view , @"topGuide": containerLeftViewController.topLayoutGuide, @"bottomGuide": containerLeftViewController.bottomLayoutGuide, }; [containerLeftViewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView]|" options:0 metrics:nil views:viewsDict]]; [containerLeftViewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[topGuide][tableView][bottomGuide]" options:0 metrics:nil views:viewsDict]]; 

Saludos, Ben

Creo que el enfoque para usar UITableViewController puede ser un poco diferente de lo que has hecho antes. Me ha funcionado, pero puede que no seas un fanático de eso. Lo que he hecho es tener un controlador de vista con una vista de contenedor que apunta a mi UItableViewController. De esta manera, puedo usar la Guía de TopLayout proporcionada en mi storyboard. Simplemente agregue la restricción a la vista de contenedor y debería ocuparse tanto de iOS7 como de iOS6.

Terminé usando una vista adicional con el fondo deseado, añadida después de TableView y colocada debajo de la barra de estado:

  self.CoverView = [[UIView alloc]init]; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { self.CoverView.frame = CGRectMake(0,0,self.view.bounds.size.width,20); } self.CoverView.backgroundColor = [UIColor whiteColor]; self.TableView = [[UITableView alloc]initWithFrame:CGRectMake(0, self.CoverView.bounds.size.height,XXX, YYY)]; [self.view addSubview:self.TableView]; [self.view addSubview:self.CoverView]; 

No es muy bonito, pero es una solución bastante simple, si necesita trabajar con vistas xib-less, y tanto IOS6 como IOS7

La siguiente solución funciona bien en el código sin usar constantes mágicas, y las cuentas para el usuario que cambian la clase de tamaño, por ejemplo, mediante rotaciones o aplicaciones paralelas en los ipads:

 - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection]; // Fix up content offset to ensure the tableview isn't underlapping the status bar. self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0.0, 0.0, 0.0); } 

Tenía un UISearchBar en la parte superior de mi UITableView y lo siguiente funcionó;

 self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0); self.tableView.contentOffset = CGPointMake(0, -20); 

Comparte y Disfruta…

He hecho esto para la pantalla Retina / No Retina como

 BOOL isRetina = FALSE; if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { if ([[UIScreen mainScreen] scale] == 2.0) { isRetina = TRUE; } else { isRetina = FALSE; } } if (isRetina) { self.edgesForExtendedLayout=UIRectEdgeNone; self.extendedLayoutIncludesOpaqueBars=NO; self.automaticallyAdjustsScrollViewInsets=NO; } 

Lo hice funcionar estableciendo el tamaño a freeform

enter image description here

La solución de Abrahamchez https://developer.apple.com/library/ios/qa/qa1797/_index.html funcionó para mí de la siguiente manera. Tenía un solo UITableviewcontroller como mi vista inicial. Probé el código de desplazamiento y la incrustación en un navegador, pero ninguno resolvió la transparencia de la barra de estado.

Agregue un Viewcontroller y conviértalo en la vista inicial. Esto debería mostrarle las Guías de diseño superior e inferior críticas.

Arrastre la vieja vista de tabla a la vista en el nuevo controlador.

Haga todo lo necesario para actualizar la tabla en el nuevo controlador:

Cambie su archivo old view controller.h para heredar / subclase de UIViewController en lugar de UITableViewController.

Agregue UITableViewDataSource y UITableViewDelegate a la .h de viewcontroller.

Vuelva a conectar todo lo que necesite en el guión gráfico, como una barra de búsqueda.

Lo importante es establecer las restricciones, como en las preguntas y respuestas de Apple. No me molesté en insertar una barra de herramientas. No estoy seguro de la secuencia exacta. Pero apareció un icono rojo en las Guías de diseño, tal vez cuando construí. Hice clic y deje que Xcode instale / limpie las restricciones.

Luego hice clic en todos lados hasta que encontré la restricción Vertical Space y cambié su valor superior de -20 a 0 y funcionó perfectamente.

Estoy usando un UISplitViewController con un navigationcontroller y un tableviewcontroller. Esto funcionó para mí en la vista maestra después de probar muchas soluciones aquí:

 float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; if (systemVersion >= 7.0f) { // Move the view down 20 pixels CGRect bounds = self.view.bounds; bounds.origin.y -= 20.0; [self.navigationController.view setBounds:bounds]; // Create a solid color background for the status bar CGRect statusFrame = CGRectMake(0.0, -20.0, bounds.size.width, 20); UIView* statusBar = [[UIView alloc] initWithFrame:statusFrame]; statusBar.backgroundColor = [UIColor whiteColor]; [statusBar setAlpha:1.0f]; [statusBar setOpaque:YES]; [self.navigationController.view addSubview:statusBar]; } 

Es similar a la solución de Hot Licks pero aplica la subvista al navigationController.

 override func viewDidLoad() { // your code if let nc = self.navigationController { yourView.frame.origin.y = nc.navigationBar.frame.origin.y + nc.navigationBar.frame.height } } 

Aquí hay un Swift 2.3. (Xcode 8.0) solución. Creé una subclase de UITableView.

 class MYCustomTableView: UITableView { override func drawRect(rect: CGRect) { super.drawRect(rect) contentInset = UIEdgeInsetsZero } } 

El contenido del recuadro siempre debe ser Cero (por defecto). Lo estoy configurando a cero manualmente. También puede agregar un método de verificación que haga la comprobación y, si es diferente de lo que desea, simplemente obtenga el rect correcto. El cambio solo se reflejará cuando se dibuje la tabla (lo que no sucede a menudo).

No se olvide de actualizar TableView en su IB (en el TableViewController o simplemente TableView dentro de su ViewController).

Funciona para swift 3 – en viewDidLoad ();

 let statusBarHeight = UIApplication.shared.statusBarFrame.height let insets = UIEdgeInsets(top: statusBarHeight, left: 0, bottom: 0, right: 0) tableView.contentInset = insets tableView.scrollIndicatorInsets = insets 

Este código: 1. Obtiene la altura de la barra de estado 2. Otorga a la parte superior de la tabla un recuadro de contenido igual al alto de la barra de estado. 3. Le da al indicador de desplazamiento el mismo recuadro, por lo que aparece debajo de la barra de estado.

Estaba enfrentando este problema en iOS 11 pero el diseño era correcto para iOS 8 – 10.3.3. Para mi caso, establecí una restricción de espacio vertical en Superview.Top Margin en lugar de Superview.Top que funciona para ios 8 – 11.

enter image description here

ver todas las soluciones: mi proyecto es solo usar xib, entonces, la solución con el guión gráfico no funcionó para mí. self.edgesForExtendedLayout = UIRectEdgeNone; solo funciona para el controlador si la barra de navegación está visible. pero si su vista solo tiene barra de estado, eso no funcionará. así que combino dos condiciones.

 - (void) viewDidLayoutSubviews { float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; if (systemVersion >= 7.0f) { CGRect bounds = self.view.bounds; if(self.navigationController == nil || self.navigationController.isNavigationBarHidden == YES){ bounds.origin.y -= 20.0; [self.view setBounds:bounds]; } else{ self.edgesForExtendedLayout = UIRectEdgeNone; } } 

ayuda esto funciona

Si también necesita soportar iOS 6, deberá moverlo de manera condicional. Es decir, en iOS 7 solo debes bajar 20 puntos (ya sea mediante la manipulación de frame o mediante el diseño automático), y en iOS 6 lo dejas en paz. No creo que puedas hacer esto en IB, así que tendrás que hacerlo en código.

EDITAR

En realidad, puede hacer esto en IB, utilizando los deltas iOS6 / iOS7. Establezca su posición en iOS 7, luego para iOS 6 configure el delta Y en -20 puntos. Vea esta pregunta SO para más información.