Explicando la diferencia entre automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout en iOS7

He estado leyendo mucho sobre la transición de IU de iOS7.

No puedo obtener lo que estas tres propiedades edgesForExtendedLayout automaticallyAdjustsScrollViewInsets , extendedLayoutIncludesOpaqueBars , edgesForExtendedLayout ??

Por ejemplo, estoy tratando de hacer que mis controladores de vista comiencen debajo de la barra de estado, pero no puedo lograrlo.

A partir de iOS7, los controladores de visualización usan el diseño de pantalla completa de forma predeterminada. Al mismo tiempo, usted tiene más control sobre cómo establece sus puntos de vista, y eso se hace con esas propiedades:

edgesForExtendedLayout

Básicamente, con esta propiedad usted establece qué lados de su vista se pueden extender para cubrir toda la pantalla. Imagina que presionas un UIViewController en un UINavigationController . Cuando se visualiza la vista de ese controlador de vista, se iniciará donde termina la barra de navegación, pero esta propiedad establecerá qué lados de la vista (arriba, izquierda, abajo, derecha) se pueden extender para llenar toda la pantalla.

Déjala ver con un ejemplo:

 UIViewController *viewController = [[UIViewController alloc] init]; viewController.view.backgroundColor = [UIColor redColor]; UINavigationController *mainNavigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; 

Aquí no está configurando el valor de edgesForExtendedLayout , por lo tanto, se toma el valor predeterminado ( UIRectEdgeAll ), por lo que la vista amplía su diseño para llenar toda la pantalla.

Este es el resultado:

sin bordes para el diseño extendido, la vista llena toda la pantalla

Como puede ver, el fondo rojo se extiende detrás de la barra de navegación y la barra de estado.

Ahora, va a establecer ese valor en UIRectEdgeNone , por lo que le está diciendo al controlador de vista que no extienda la vista para cubrir la pantalla:

 UIViewController *viewController = [[UIViewController alloc] init]; viewController.view.backgroundColor = [UIColor redColor]; viewController.edgesForExtendedLayout = UIRectEdgeNone; UINavigationController *mainNavigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; 

Y el resultado:

con el conjunto edgesForExtendedLayout, la vista se encuentra justo debajo de la navegación

Ajusta automáticamenteScrollViewInsets

Esta propiedad se usa cuando su vista es un UIScrollView o similar, como una UITableView . Desea que su tabla comience donde termina la barra de navegación, porque no verá todo el contenido si no es así, pero al mismo tiempo desea que su tabla cubra toda la pantalla cuando se desplaza. En ese caso, establecer edgesForExtendedLayout en None no funcionará porque su tabla comenzará a desplazarse donde termina la barra de navegación y no irá detrás de ella.

Aquí es donde esta propiedad es útil, si permite que el controlador de vista ajuste automáticamente las inserciones (estableciendo esta propiedad en SÍ, también el valor predeterminado) agregará inserciones en la parte superior de la tabla, de modo que la tabla se iniciará donde la navegación la barra termina, pero el rollo cubrirá toda la pantalla.

Esto es cuando se establece en NO:

la tabla se desplazará por toda la pantalla, pero comienza parcialmente cubierta

Y SÍ (por defecto):

la mesa se desplaza por toda la pantalla y comienza justo debajo de la navegación

En ambos casos, la tabla se desplaza detrás de la barra de navegación, pero en el segundo caso (SÍ), comenzará desde debajo de la barra de navegación.

extendedLayoutIncludesOpaqueBars

Este valor es solo una adición a los anteriores. Por defecto, este parámetro está establecido en NO. Si la barra de estado es opaca, las vistas no se extenderán para incluir la barra de estado, incluso si extiende su vista para cubrirla ( edgesForExtendedLayout to UIRectEdgeAll ).

Si establece el valor en SÍ, esto permitirá que la vista vaya por debajo de la barra de estado nuevamente.

Si algo no está claro, escribe un comentario y lo responderé.

¿Cómo sabe iOS qué UIScrollView usar?

iOS toma la primera subvista en la vista de ViewController, la del índice 0, y si es una subclase de UIScrollView , aplica las propiedades explicadas.

Por supuesto, esto significa que UITableViewController funciona de manera predeterminada (ya que UITableView es la primera vista).

No estoy seguro de si está utilizando guiones gráficos, pero si lo está, para hacer que sus controladores de vista comiencen debajo de la barra de estado (y encima de la barra inferior):

Seleccione el controlador de vista en IB, en el inspector de atributos, anule la selección de ‘Extender bordes – Bajo barras superiores’ y ‘Extender bordes – Bajo barras inferiores’.

Estoy usando guiones gráficos y el uso de los consejos anteriores funcionó, sin embargo, no estaba exactamente seguro de cómo implementarlo. A continuación se muestra un breve ejemplo de cómo solucionó el problema al poner la solución recomendada en ViewController.

 import Foundation import UIKit // This ViewController is connected to a view on a storyboard that // has a scrolling sub view. class TheViewController: UIViewController { // Prepares the view prior to loading. Putting it in viewDidAppear didn't work. override func viewWillAppear(animated: Bool) { // this method is an extension of the UIViewController // so using self works as you might expect. self.automaticallyAdjustsScrollViewInsets = false // Default is "true" so this sets it to false tells it to use // the storyboard as you have it placed // and not how it thinks it should place it. } } 

Mi problema: Ajuste automático establecido en verdadero por defecto, lo que causa una diferencia entre el diseño del guión gráfico y el simulador Auto Adjust establecido en true de forma predeterminada causando una diferencia entre el diseño del guión gráfico y el simulador

Resuelto: Código anterior aplicado, desactivando el autoajuste. Código anterior aplicado, desactivando el autoajuste.

Resolví este problema agregando esta línea, pero mi problema estaba relacionado con un UIView , no UIScrollView

 self.navigationController.navigationBar.translucent = NO; 

Solo tenga en cuenta que automaticallyAdjustsScrollViewInsets propiedad de ajuste automaticallyAdjustsScrollViewInsets ScrollViewInsets solo funciona si algún tipo de vista de desplazamiento (vista de tabla, vista de colección, …) es cualquiera

  • La vista de VC, o
  • Primera subvista de esta vista

Otro sugirió que funciona aunque sea la primera subvista, pero hay otras vistas de desplazamiento en la jerarquía de vistas.

EDITAR (extensión DIY)

Si desea un comportamiento similar incluso si no puede cumplir con estas condiciones (por ejemplo, tiene una imagen de fondo debajo de la vista de desplazamiento), puede ajustar manualmente las inserciones de la vista de desplazamiento. Pero, por favor, no lo configuren en constante como 44 o 64 o incluso 20 como muchos sugieren alrededor de SO. No puedes saber el tamaño nunca. Puede haber una notificación de incall / gps / audio, la barra de navegación no tiene que ser siempre de 44 puntos, etc.

Creo que la mejor solución es usar la length de la guía de diseño en didLayoutSubviews:

 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() scrollView.contentInset = UIEdgeInsets(top: topLayoutGuide.length, left: 0, bottom: 0, right: 0) scrollView.scrollIndicatorInsets = scrollView.contentInset } 

Puede usar bottomLayoutGuide de la misma manera.