ios ios7 uistatusbar

iOS 7: UITableView se muestra debajo de la barra de estado



ios7 uistatusbar (26)

La primera pantalla de mi aplicación es un UITableViewController sin barra de navegación, lo que significa que el contenido fluye bajo la barra de estado, por lo que hay muchas colisiones de texto. He ajustado ambas propiedades para Under top bars y Adjust scroll view insets que realmente impiden que se desplace hacia abajo, pero al costo de mantener la parte superior de la vista de tabla debajo. He intentado configurar el marco de la UITableView para que se UITableView en 20 píxeles, pero no parece que tenga efecto y, dado que actualmente necesito que la aplicación sea compatible con iOS 6, no puedo saltar a iOS 7 Storyboards para forzar la reproducción automática. Utilice la guía de altura superior. ¿Alguien ha encontrado una solución que funcione para ambas versiones?

Cosas que he intentado: configuración de edgesForExtendedLayout , cambio de la configuración dentro del guión gráfico para Under top bars y Adjust scroll view , forzando el marco a una nueva área.

Una imagen vale mas que mil palabras:


Agregando a la respuesta superior:

después de que el segundo método no pareció funcionar inicialmente, hice algunos retoques adicionales y encontré la solución.

TLDR; la segunda solución de la respuesta principal casi funciona, pero para algunas versiones de xCode ctrl + arrastrando a la "Guía de diseño superior" y seleccionar Espaciado vertical no hace nada. Sin embargo, al primero ajustar el tamaño de la Vista de tabla y luego seleccionar "Espacio superior a la Guía de diseño superior" funciona

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

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

  1. Arrastre un UITableViewCell en el TableView. Esta será su celda de reutilización de prototipo, así que no olvide configurar su Identificador de Reutilización en la pestaña Atributos o se bloqueará.
  1. Cree su subclase personalizada de UIViewController y agregue los <UITableViewDataSource, UITableViewDelegate> . No olvide configurar el ViewController de su guión gráfico para esta clase en el inspector de identidad.

  2. Cree una salida para su TableView en su archivo de implementación, y denomínelo "tableView"

  1. Haga clic derecho en TableView y arrastre tanto el DataSource como el delegado a su ViewController.

Ahora para la parte de no recortar en la barra de estado.

  1. Tome el borde superior de su Vista de tabla y muévalo hacia abajo a una de las guías de diseño automático azul discontinuas que están cerca de la parte superior
  1. Ahora, puede controlar el arrastre desde la vista de tabla hasta la parte superior y seleccionar la guía de Top Space to Top Layout
  1. Te dará un error sobre el diseño ambiguo de TableView, solo agrega Restricciones faltantes y listo.

Ahora puede configurar su vista de tabla como de costumbre, ¡y no recortará la barra de estado!


Aquí hay un Swift 2.3. (Xcode 8.0) solución. He creado 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 (de forma predeterminada). Lo estoy poniendo a cero manualmente. También puede agregar un método de verificación que haga la verificación y, si es algo distinto a lo que desea, solo obtenga el correcto. El cambio se reflejará solo cuando se dibuje la vista de tabla (lo que no sucede a menudo).

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


Así es como se escribe en "Swift" Un ajuste a la respuesta de @ lipka:

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


Creo que el enfoque para utilizar UITableViewController puede ser un poco diferente de lo que has hecho antes. Me ha funcionado, pero puede que no seas un fanático de ello. 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 el TopLayoutGuide proporcionado en mi guión gráfico. Simplemente agregue la restricción a la vista de contenedor y debe estar atento a iOS7 y iOS6.


Esto lo arreglará para un UITableViewController (sin ningún número mágico). Lo único que no pude solucionar es si está realizando una llamada telefónica, en cuyo caso la parte superior de la tableView se presiona demasiado. Si alguien sabe cómo resolverlo, 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 } }


Estoy utilizando un UISplitViewController con un controlador de navegación y un controlador de vista de tabla. 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.


He hecho esto para Retina / Non-Retina display 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; }


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

Encontré que la solución más limpia al crear TableViewControllers mediante programación es envolver la instancia de UITableViewController en otro UIViewController y establecer 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


La siguiente solución funciona lo suficientemente bien en el código sin usar constantes mágicas, y da cuenta de que el usuario cambia la clase de tamaño, por ejemplo, mediante rotaciones o aplicaciones en paralelo 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); }


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 controlador de vista de UIT como mi vista inicial. Probé el código de compensación e incrusté en un navegador, pero ninguno resolvió la transparencia de la barra de estado.

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

Arrastre la Tableview antigua a la Vista en el nuevo controlador.

Haga todo lo necesario para adaptar la tabla al nuevo controlador:

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

Agregue UITableViewDataSource y UITableViewDelegate al controlador de visualización .h.

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

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

Luego hice clic en todas partes hasta que encontré la restricción del espacio vertical y cambié su valor superior de -20 a 0 y funcionó perfectamente.


Lo tengo funcionando ajustando el tamaño a la forma libre


Me enfrentaba a este problema en ios 11, pero el diseño era correcto para ios 8 - 10.3.3. Para mi caso, puse una restricción de espacio vertical en Superview.Top Margin en lugar de Superview.Top que funciona para ios 8 - 11.


No sé qué tan kosher es, pero descubrí que este esquema mueve hacia abajo la vista del Controlador de Vista y proporciona la barra de estado con 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, reemplaza el color redColor con el color que quieras para el fondo.

Debe hacer por separado uno de los swizzles 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 la lista, para hacer esto globalmente.

Parece que funciona, y me interesaría saber de cualquier error o problema con él.


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


Para aquellos como yo que preferirían no incrustar su UITableViewController en un UIViewController intente esto:

Una subclase UITableViewController personalizada puede agregar una vista de máscara a la vista de tabla de la vista de tabla. Agregue la máscara en viewDidAppear y elimine la máscara en viewWillDisappear.

private var statusBarMaskView: UIView! override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if let superview = self.tableView.superview { self.statusBarMaskView = UIView(frame: CGRect.zero) superview.insertSubview(self.statusBarMaskView, aboveSubview: self.tableView) self.statusBarMaskView.backgroundColor = self.tableView.backgroundColor // using a nice constraint layout library to set the frame self.statusBarMaskView.pinTop(to: superview) self.statusBarMaskView.pinLeft(to: superview) self.statusBarMaskView.pinRight(to: superview) self.statusBarMaskView.addHeightConstraint(with: 22.0) //// } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) self.statusBarMaskView.removeFromSuperview() self.statusBarMaskView = nil }


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

  1. Crea un nuevo proyecto iOS
  2. Abra el guión gráfico principal y elimine el UIViewController predeterminado / inicial
  3. Arrastre un nuevo UITableViewController desde la biblioteca de objetos
  4. Establézcalo como el controlador de vista inicial
  5. Alimentar la tabla algunos datos de prueba

Si sigue los pasos anteriores, cuando ejecute la aplicación, verá que nada, incluyendo el ajuste de las casillas de verificación de Xcode a "Extender bordes debajo de {Top, Bottom, Opaque} Bars", impide que la primera fila aparezca debajo de la barra de estado. ni puedes 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 en el extremo de Apple, especialmente porque aparece en su propio UITableViewController precableado desde la biblioteca de objetos.

No estoy de acuerdo con todos los que intentan resolver esto utilizando cualquier forma de "Números mágicos", por ejemplo, "use un delta de 20px". Este tipo de programación estrechamente acoplada definitivamente no es lo que Apple quiere que hagamos aquí.

He descubierto dos soluciones a este problema:

  • Preservando la UITableViewController del 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 deseleccionar "Muestra la barra de navegación" en el inspector. Esto resuelve el problema sin necesidad de ajustes adicionales, y también conserva la UITableViewController su UITableViewController en el guión gráfico.

  • Usando AutoLayout e incrustando el 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 Autolayout que dice "Guía de diseño superior". Suelte el ratón y seleccione "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 en su proyecto.


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


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

Swift 3

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

Antes Swift

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 desplace hacia la parte superior.


Si también necesitas soportar iOS 6, deberás moverlo hacia abajo de manera condicional. Es decir, en iOS 7 solo debes moverlo hacia abajo 20 puntos (ya sea a través de la manipulación de frame o utilizando el diseño automático), y en iOS 6 lo dejas solo. 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 de 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.


Tenía una barra UISearch en la parte superior de mi UITableView y funcionó lo siguiente;

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

Comparte y Disfruta...


Terminé usando una vista adicional con el fondo deseado, añadido después de TableView y colocado 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 sin xib, y tanto IOS6 como IOS7


Works 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. Da a la parte superior de la vista de tabla una inserción de contenido igual a la altura de la barra de estado. 3. Le da al indicador de desplazamiento la misma inserción, por lo que aparece debajo de la barra de estado.


vea todas las soluciones: mi proyecto es solo usar xib, así que la solución con storyboard no funcionó para mí. self.edgesForExtendedLayout = UIRectEdgeNone; Simplemente funciona para el controlador si la barra de navegación es visible. pero si su vista es simplemente tener 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.


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

  • No hay 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 los dos requisitos anteriores no se cumplen, su kilometraje puede variar.

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

Source (en la sección topLayoutGuide al final de la página 39).


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


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