Explicando la diferencia entre automáticamente AjustaScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgeForExtendedLayout en iOS7

250

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

No soy capaz de conseguir lo que estas tres propiedades 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.

usuario1010819
fuente
55
y ¿por qué piensa que no he leído que .. El problema es que no funciona como se espera, como en que no he entendido bien !! .. esa es la razón?
user1010819
1
Ohhh, entendí mal lo que estabas diciendo allí. No estaba tratando de parecer condescendiente, es solo que cuando algunas personas hacen preguntas como esta, y son nuevos en el sitio, pierden las soluciones obvias.
erdekhayser
8
En su método viewDidLoad, agregue if ([self responddsToSelector: @selector (edgeForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone; lo que obligará a que su vista comience debajo de la barra de estado.
Nandha

Respuestas:

629

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

edgeForExtendedLayout

Básicamente, con esta propiedad usted establece qué lados de su vista se pueden extender para cubrir toda la pantalla. Imagina que empujas un UIViewControllera UINavigationController. Cuando se presenta la vista de ese controlador de vista, comenzará 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.

Veamos 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 extiende su diseño para llenar toda la pantalla.

Este es el resultado:

sin bordes para un diseño extendido, la vista ocupa 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 bordesForExtendedLayout establecido, la vista está justo debajo de la navegación


automaticAdjustsScrollViewInsets

Esta propiedad se usa cuando su vista es una UIScrollViewo similar, como una UITableView. Desea que su tabla comience donde termina la barra de navegación, porque de lo contrario no verá todo el contenido, pero al mismo tiempo desea que su tabla cubra toda la pantalla al desplazarse. En ese caso, establecerlo edgesForExtendedLayouten Ninguno no funcionará porque su tabla comenzará a desplazarse hacia donde termina la barra de navegación y no irá detrás de ella.

Aquí es donde esta propiedad es útil, si deja 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, por lo que la tabla comenzará donde la navegación la barra termina, pero el desplazamiento 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 tabla 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 ( edgesForExtendedLayouta UIRectEdgeAll).

Si establece el valor en SÍ, esto permitirá que la vista vuelva a estar debajo de la barra de estado.

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 su ViewController, la que está en el índice 0, y si es una subclase de, UIScrollViewentonces le aplica las propiedades explicadas.

Por supuesto, esto significa que UITableViewControllerfunciona de forma predeterminada (ya que UITableViewes la primera vista).

Antonio MG
fuente
Necesitamos establecer estas propiedades solo si, estamos mostrando la barra de navegación predeterminada, y no si su barra de navegación personalizada, ¿verdad?
Hemang
1
No, si usa la barra de navegación de iOS pero con su propio diseño, deberá usar las mismas propiedades. Si solo crea su barra de navegación desde cero, entonces esas propiedades no funcionarán.
Antonio MG
No entiendo por qué aparece una pequeña capa negruzca en toda la vista. ¿Por favor ayuda? : /
aZtraL-EnForceR
24
Esta explicación es mucho mejor que la Guía de transición de la interfaz de usuario de iOS 7. Esto debería reemplazar la guía, que no tenía sentido para mí.
Sam
2
Creo que extendedLayoutIncludesOpaqueBars debería ser YES por defecto en lugar de NO. Cambiar los colores de la vista (translucidez) no debería afectar el diseño.
Vladimír Slavík
15

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

Seleccione el controlador de vista en IB. En el inspector de atributos, anule la selección de 'Extender bordes: debajo de las barras superiores' y 'Extender bordes: debajo de las barras inferiores'.

Ali Beadle
fuente
OKAY. Entonces creo que lo que Nandha sugirió anteriormente logrará el mismo resultado programáticamente. Si no funciona en viewDidLoad, es posible que deba moverse para ver viewDidLayoutSubviews.
Ali Beadle
Indica si el diseño extendido incluye o no barras opacas. @property (no atómico, asignar) BOOL extendedLayoutIncludesOpaqueBars Discussion El valor predeterminado es NO.
Abdul Yasin
+1, me diste una pista para revisar Storyboard. Y resolví la mitad de mi problema.
selva
10

Estoy usando guiones gráficos y los consejos anteriores funcionaron, 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 el 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 de forma predeterminada, lo que causa una diferencia entre el diseño del guión gráfico y el simulador Ajuste automático establecido en verdadero de forma predeterminada, lo que causa una diferencia entre el diseño del guión gráfico y el simulador

Resuelto: se aplicó el código anterior, desactivando el ajuste automático. Se aplicó el código anterior, desactivando el ajuste automático.

Christopher Wade Cantley
fuente
55
si activa el valor de AutomaticAdjustsScrollViewInsets como SÍ, debe establecer la restricción superior para supervisar, no la topGuideLayout.
xmkevinchen
5

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

self.navigationController.navigationBar.translucent = NO;
usuario3430340
fuente
2

Solo tenga en cuenta que la automaticallyAdjustsScrollViewInsets propiedad solo funciona si algún tipo de vista de desplazamiento (vista de tabla, vista de colección, ...)

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

Otro sugirió que funciona incluso si es 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 estas condiciones (por ejemplo, tiene una imagen de fondo debajo de la vista de desplazamiento), puede ajustar las inserciones de la vista de desplazamiento manualmente. Pero por favor no lo establezca en constante como 44 o 64 o incluso 20 como muchos sugieren alrededor de SO. No se puede saber el tamaño nunca. Puede haber una notificación de llamada / gps / audio, la barra de navegación no tiene que ser siempre 44 pts, etc.

Creo que la mejor solución es usar layoutGuide lengthen 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.

Vojta Rujbr
fuente
Y obviamente la barra de navegación es translúcida.
Vojta Rujbr