La barra de estado y la barra de navegación aparecen sobre los límites de mi vista en iOS 7

435

Recientemente descargué Xcode 5 DP para probar mis aplicaciones en iOS 7. Lo primero que noté y confirmé es que los límites de mi vista no siempre cambian de tamaño para tener en cuenta la barra de estado y la barra de navegación.

En viewDidLayoutSubviews, imprimo los límites de la vista:

{{0, 0}, {320, 568}}

Esto hace que mi contenido aparezca debajo de la barra de navegación y la barra de estado.

Sé que podría explicar la altura yo mismo obteniendo la altura de la pantalla principal, restando la altura de la barra de estado y la altura de la barra de navegación, pero eso parece un trabajo adicional innecesario.

¿Cómo puedo solucionar este problema?

Actualizar:

He encontrado una solución para este problema específico. Establezca la propiedad translúcida de la barra de navegación en NO:

self.navigationController.navigationBar.translucent = NO;

Esto solucionará que la vista se enmarque debajo de la barra de navegación y la barra de estado.

Sin embargo, no he encontrado una solución para el caso cuando desea que la barra de navegación sea translúcida. Por ejemplo, al ver una foto a pantalla completa, deseo que la barra de navegación sea translúcida y que la vista se enmarque debajo de ella. Eso funciona, pero cuando alterno mostrar / ocultar la barra de navegación, he experimentado resultados aún más extraños. La primera subvista (un UIScrollView) tiene sus límites y el origen cambia cada vez.

abeja
fuente
También recibo el mismo problema en xcode 5 DP
Gopesh Gupta
Avíseme si obtendrá alguna solución
Gopesh Gupta
1
Busque en la barra de navegación una propiedad de color de tinte, debería poder cambiar ese color azul a lo que quiera.
beebcon
99
A veces odio la actualización de iOS porque Apple nunca te dio la oportunidad de mantener tu aplicación compatible con versiones anteriores.
Bagusflyer
3
Si el problema está relacionado con la vista que se encuentra debajo de la barra de estado después de ocultar la barra superior del controlador de navegación, me referiría a la respuesta de @Stunner stackoverflow.com/a/18976660/235206 como la solución
MiKL

Respuestas:

495

Puede lograr esto implementando una nueva propiedad llamada edgesForExtendedLayouten iOS7 SDK. Agregue el siguiente código para lograr esto,

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

Necesita agregar lo anterior en su -(void)viewDidLoadmétodo.

iOS 7 trae varios cambios en la forma en que diseñas y personalizas la apariencia de tu interfaz de usuario . Los cambios en el diseño del controlador de vista, el color del tinte y la fuente afectan a todos los objetos UIKit en su aplicación. Además, las mejoras en las API de reconocimiento de gestos le brindan un control más preciso sobre las interacciones de gestos.

Uso de controladores de vista

En iOS 7, los controladores de vista usan un diseño de pantalla completa. Al mismo tiempo, iOS 7 le brinda un control más granular sobre la forma en que un controlador de vista presenta sus vistas. En particular, el concepto de diseño de pantalla completa se ha refinado para permitir que un controlador de vista especifique el diseño de cada borde de su vista.

La wantsFullScreenLayoutpropiedad del controlador de vista está en desuso en iOS 7. Si actualmente especifica wantsFullScreenLayout = NO, el controlador de vista puede mostrar su contenido en una ubicación de pantalla inesperada cuando se ejecuta en iOS 7.

Para ajustar cómo un controlador de vista presenta sus vistas, UIViewController proporciona las siguientes propiedades:

  • edgeForExtendedLayout

La edgesForExtendedLayoutpropiedad usa el UIRectEdgetipo, que especifica cada uno de los cuatro bordes de un rectángulo, además de especificar ninguno y todos. Se usa edgesForExtendedLayoutpara especificar qué bordes de una vista deben extenderse, independientemente de la translucidez de la barra. Por defecto, el valor de esta propiedad es UIRectEdgeAll.

  • extendedLayoutIncludesOpaqueBars

Si su diseño usa barras opacas, refine edgesForExtendedLayoutestableciendo también la extendedLayoutIncludesOpaqueBarspropiedad en NO . (El valor predeterminado de extendedLayoutIncludesOpaqueBarses NO ).

  • automaticAdjustsScrollViewInsets

Si no desea que las inserciones de contenido de una vista de desplazamiento se ajusten automáticamente, ajústelo automaticallyAdjustsScrollViewInsetsen NO . (El valor predeterminado de automaticallyAdjustsScrollViewInsetses ).

  • topLayoutGuide, bottomLayoutGuide

Las propiedades topLayoutGuidey bottomLayoutGuideindican la ubicación de los bordes de la barra superior o inferior en la vista de un controlador de vista. Si las barras se superponen en la parte superior o inferior de una vista, puede usar el Creador de interfaces para colocar la vista en relación con la barra creando restricciones en la parte inferior topLayoutGuideo superior de la Guía de diseño. (Si no hay barras superpuestas en la vista, la parte inferior de topLayoutGuidees la misma que la parte superior de la vista y la parte superior bottomLayoutGuidees la misma que la parte inferior de la vista). Ambas propiedades se crean perezosamente cuando se solicitan.

Consulte, documento de apple

Nandha
fuente
2
No se compilará bajo iOS6. Creo que debería escribirse como performanceselector ...
Shmidt
8
Sí, es por eso que he incluido la verificación del selector con la condición if, if ([self responddsToSelector: @selector (edgeForExtendedLayout)])
Nandha
19
Esto no funcionaría si no tengo barra de navegación. En ese caso, mi vista se extiende detrás de la barra de estado ..
Van Du Tran
44
Tengo el mismo problema que @VanDuTran. edgeForExtendedLayout no ayuda si la barra de navegación está oculta.
fishinear
66
funciona, pero ... ya no hay efecto translúcido ... ¿cómo podemos preservar el efecto translúcido también ...
Dipu Rajak
110

No tiene que calcular qué tan lejos puede desplazar todo hacia abajo, hay una propiedad incorporada para esto. En Interface Builder, resalte su controlador de vista y luego navegue al inspector de atributos. Aquí verá algunas casillas de verificación junto a las palabras "Extender bordes". Como puede ver, en la primera captura de pantalla, la selección predeterminada es que el contenido aparezca debajo de las barras superior e inferior, pero no debajo de las barras opacas, por lo que configurar el estilo de barra para que no sea translúcido funcionó para usted.

Como puede ver en la primera captura de pantalla, hay dos elementos de la interfaz de usuario ocultos debajo de la barra de navegación. (He habilitado wireframes en IB para ilustrar esto) Estos elementos, un UIButton y un UISegmentedControl tienen su origen "y" establecido en cero, y el controlador de vista está configurado para permitir contenido debajo de la barra superior.

ingrese la descripción de la imagen aquí

Esta segunda captura de pantalla muestra lo que sucede cuando desmarca la casilla de verificación "Bajo las barras superiores". Como puede ver, la vista de los controladores de vista se ha desplazado hacia abajo de manera apropiada para que su origen esté justo debajo de la barra de navegación.

ingrese la descripción de la imagen aquí

Esto también se puede lograr mediante programación mediante el uso de -[UIViewController edgesForExtendedLayout]. Aquí hay un enlace a la referencia de clase para edgeForExtendedLayout y para UIRectEdge

[self setEdgesForExtendedLayout:UIRectEdgeNone];
Mick MacCallum
fuente
15
¿Cómo hago lo mismo solo para ver en un .xib?
Bobics
2
Agregué
55
@bobics La respuesta a la pregunta XIB es: "No puedes". No a través del IB de todos modos. Archiva un radar y espera que Apple finalmente lo aborde.
memmons
Gracias @ 0x7fffffff, esta fue solo la información que estaba buscando y fue muy útil.
campo
33

Creé mi vista mediante programación y esto terminó funcionando 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 topLayoutGuide en la parte inferior de la página 39).

Persona maravillosa
fuente
Finalmente encontré una respuesta que realmente funciona para esto. ¡Buen trabajo!
StuartM
1
Para resolver el problema por el cual la vista del controlador de vista aparece debajo de la barra de estado cuando la barra de navegación está oculta, este es el código que ajusta la vista debajo de la barra de estado.
MiKL
Nota: esto empujará la parte inferior de su vista fuera de la pantalla.
memmons
1
Además, a menos que esté compilando solo para iOS7, el código anterior arrojará un error, topLayoutGuidees solo iOS7.
memmons
1
También tenga en cuenta que cuando su vista principal es UITableView, se llamará a viewDidLayoutSubviews en cada desplazamiento. Su UITableView se reducirá hasta que su altura sea de 15 px. Agregue una bandera para ejecutar este código solo una vez. ;)
Thomas Johannesmeyer
30

Solución Swift 3 / Swift 4 que también funciona con archivos NIB / XIB en iOS 10+:

override func viewDidLoad() {
    super.viewDidLoad()

    edgesForExtendedLayout = []
}
flo_23
fuente
Esto es lo que me ayudó ... Tan simple. Gracias :-)
Hernan Arber
Gracias, es realmente útil
Muhammad Ahmed Baig
Esta es la mejor solución para 10.x Swift 3+ IMO
shokaveli
10

Si desea que la vista tenga la barra de navegación translúcida (que es bastante agradable), debe configurar un ContentInset o similar.

Así es como lo hago:

// Check if we are running on ios7
if([[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."][0] intValue] >= 7) {
      CGRect statusBarViewRect = [[UIApplication sharedApplication] statusBarFrame];
      float heightPadding = statusBarViewRect.size.height+self.navigationController.navigationBar.frame.size.height;

      myContentView.contentInset = UIEdgeInsetsMake(heightPadding, 0.0, 0.0, 0.0);
}
Magnus
fuente
3
¿por qué no puedes compararlo directamente con 7.0?
Leena
1
jajaja lo entiendo: comparar con una versión específica con menor agregado es menos robusto. Pero está comprobando si el valor es MÁS GRANDE o igual, por lo que comparar con 7.0 funcionaría bien aquí;)
EeKay
1
@leena: esta es una característica de 7.xy versiones posteriores, así que verifico si la versión es 7 o superior y omito las revisiones menores en la verificación.
Magnus
2
Tuve un problema con mi tableView que se muestra detrás de mi Tabbar. Lo que hizo que la última fila de mi tabla nunca se desplazara por encima de la barra de pestañas. Lo arreglé así: myTableView.contentInset = UIEdgeInsetsMake (0, 0.0, TabbarHeight, 0)
James Laurenstin
contentInsetes propiedad de UIScrollView. ¿Qué pasa si mi vista principal no es una subclase de UIScrollView. Entonces, ¿cómo solucionaría el problema de superposición?
Pwner
9

edgesForExtendedLayouthace el truco para iOS 7. Sin embargo, si compila la aplicación en iOS 7 SDK y la implementa en iOS 6, la barra de navegación parece translúcida y las vistas van debajo de ella. Entonces, para solucionarlo tanto para iOS 7 como para iOS 6, haga esto:

self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;   // iOS 7 specific
Raj Pawan Gumdal
fuente
9

En su archivo de aplicaciones, agregue una fila, llámelo "Ver la apariencia de la barra de estado basada en el controlador" y configúrelo en NO .

Idan
fuente
7

El truco más simple es abrir el archivo NIB y realizar estos dos simples pasos:

  1. Solo alterna eso y configúralo en el que prefieras:

Ingrese la descripción de la imagen aquí

  1. Seleccione los UIView's / UIIMageView's / ... que desea mover hacia abajo. En mi caso, solo el logotipo se superpuso y establecí el delta en +15; (O -15 si eligió iOS 7 en el paso 1)

Ingrese la descripción de la imagen aquí

Y el resultado :

antes de Después

Riskov
fuente
66
Funciona, pero parece una solución difícil de mantener. Sería mejor solucionar el problema en lugar de parchearlo.
NLemay
sería mejor hacerlo programáticamente para todas las subvistas de vistas porque no funciona si se aplica a la vista principal
wildmonkey
5

Solución rápida:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.edgesForExtendedLayout = UIRectEdge.None
}
fatihyildizhan
fuente
44
Esto es ahora edgeForExtendedLayout = []
Leon
1
Como esta es una respuesta pública, no debemos olvidar llamar:super.viewWillAppear(animated)
prodos
4

Me gustaría ampliar la respuesta de Stunner y agregar una ifdeclaración para verificar si es iOS-7, porque cuando lo probé en iOS 6 mi aplicación se bloqueó.

La adición sería agregar:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

Por lo tanto, sugeriría agregar este método a su MyViewControler.marchivo:

- (void) viewDidLayoutSubviews {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;
        viewBounds.origin.y = topBarOffset * -1;
        self.view.bounds = viewBounds;
    }
}
werdsackjon
fuente
4

Swift 3

override func viewWillAppear(_ animated: Bool) {
    self.edgesForExtendedLayout = []
}
Shahrukh
fuente
3

Tengo un escenario en el que uso el BannerViewController escrito por Apple para mostrar mis anuncios y un ScrollViewController incrustado en el BannerViewController.

Para evitar que la barra de navegación oculte mi contenido, tuve que hacer dos cambios.

1) Modificar BannerViewController.m

- (void)viewDidLoad
{
   [super viewDidLoad];
   float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
   if (systemVersion >= 7.0) {
      self.edgesForExtendedLayout = UIRectEdgeNone;
   }
}

2) Modificar mi ScrollViewContoller

- (void)viewDidLoad
{
    [super viewDidLoad];
    float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (systemVersion >= 7.0) {
        self.edgesForExtendedLayout = UIRectEdgeBottom;
    }
}

Ahora los anuncios se muestran correctamente en la parte inferior de la vista en lugar de estar cubiertos por la barra de navegación y el contenido en la parte superior no se corta.

Xavier John
fuente
2

simplemente configure el siguiente código a la vista aparecerá.

  if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) {
self.edgesForExtendedLayout = UIRectEdgeNone;
 }
Amit Shelgaonkar
fuente
Esto es lo único que funcionó en mi circunstancia.
goobliata
2

hacer restricciones al diseño superior como este ingrese la descripción de la imagen aquí

carmen_munich
fuente
2

Swift 4.2 - Xcode 10.0 - iOS 12.0:

if #available(iOS 11.0, *) {} else {
  self.edgesForExtendedLayout = []
  self.navigationController?.view.backgroundColor = .white
}
juliancadi
fuente
1

Para mí, la solución más simple es agregar dos claves al plist

ingrese la descripción de la imagen aquí

giuseppe
fuente
+1, tenía la "Barra de estado inicialmente oculta" = SÍ, pero al agregar "Ver la apariencia de la barra de estado basada en el controlador" = NO me deshice de la barra de estado.
Jonas Byström
1

Agregue la clave "Ver la apariencia de la barra de estado basada en el controlador" de la lista desplegable como una fila info.plist. Algo como esto:

Ingrese la descripción de la imagen aquí

Kursat Turkay
fuente
Interesante. Me ayudó en mis proyectos de Cocos2d. Al alternar esta opción, puedo ver que la barra de estado superior ha desaparecido o aparece por completo.
Kursat Turkay
1

Tuve el mismo problema con mi aplicación de iPads (armv7, armv7s, amr64) solo al presentar otro UIViewController y después de descartarlos, aparece la barra de navegación debajo de la barra de estado ... Dedico mucho tiempo a encontrar una solución para eso. Estoy usando el guión gráfico y en InterfaceBuilder para UIViewController, lo que hace que sea terrible configuré Presentación desde Pantalla completa -> Contexto actual y solucionó este problema. ¡Funciona en mi aplicación solo para iPads => iOS8.0 (prueba con iOS8.1) y para iPads con iOS 7.1 no funciona!ver captura de pantalla

Alexej W.
fuente
En mi caso, mi vista principal se superponía a mi tabBar y no tenía idea de por qué. Resulta que se seleccionó Extender bordes> Debajo de las barras inferiores. Fue realmente difícil notarlo porque el fondo de mi aplicación era blanco y solo generaba cierta opacidad de nivel sobre mi tabBar. ¡Gracias!
Jesus Rodriguez
0

Pasos para ocultar la barra de estado en iOS 7:

1.Vaya al archivo info.plist de su aplicación.

2.Y establecer, ver la apariencia de la barra de estado basada en el controlador: booleano NO

Espero haber resuelto el problema de la barra de estado .....

chandrika
fuente
0

En mi caso, tener loadView () interrumpió
este código: self.edgesForExtendedLayout = UIRectEdgeNone

pero después de eliminar loadView () todo funcionó bien

DevB2F
fuente