bar ios uicollectionview uikit ios11 iphone-x

ios - bar - iphone x layout



UICollectionView en paisaje en iPhone X (4)

Cuando se usa el paisaje de iPhone X, se supone que debes verificar safeAreaInsets para hacer cunetas adecuadamente grandes a la izquierda y a la derecha. UITableView tiene la nueva propiedad insetsContentViewsToSafeArea (valor predeterminado verdadero) para mantener automáticamente el contenido de la celda en el área segura.

Me sorprende que UICollectionView no parezca tener algo similar. Me gustaría que para una vista de colección de desplazamiento vertical, los lados izquierdo y derecho se inserten en el área segura cuando está en el paisaje (y por el contrario, una vista de colección de desplazamiento horizontal se inserta si es necesario en el retrato).

La forma más sencilla de garantizar este comportamiento parece ser agregar al controlador de vista de colección:

- (void)viewSafeAreaInsetsDidChange { [super viewSafeAreaInsetsDidChange]; UIEdgeInsets contentInset = self.collectionView.contentInset; contentInset.left = self.view.safeAreaInsets.left; contentInset.right = self.view.safeAreaInsets.right; self.collectionView.contentInset = contentInset; }

... suponiendo que contentInset.left / right normalmente sea cero.

(NOTA: sí, para un UICollectionViewController, que necesita ser self.view.safeAreaInsets ; en el momento en que se llama, el cambio a safeAreaInsets extrañamente aún no se ha propagado a self.collectionView )

¿Me estoy perdiendo de algo? Ese texto repetitivo es bastante simple, pero ahora es efectivamente necesario para cada vista de colección que toque un borde de pantalla. Parece realmente extraño que Apple no haya proporcionado algo para habilitar esto de forma predeterminada.


UICollectionView pretende ser flexible para una amplia variedad de diseños. Los diseños más comunes son cuadrículas con múltiples filas y columnas, pero es posible crear diseños que no sean de cuadrícula con UICollectionView .

UITableView , por otro lado, está diseñado para celdas de ancho completo.

Por lo tanto, tiene sentido que UITableView tenga soporte integrado para tratar con UITableView área seguros, ya que los diseños de vista de tabla siempre se verán afectados por él. Debido a que UICollectionView usa diseños personalizados, tiene sentido resolver estos problemas por implementación en lugar de tratar de proporcionar una solución única para todos.


Si bien Nathan tiene razón acerca de la versatilidad de UICollectionView con varios diseños, me preocupaba principalmente el caso "predeterminado" en el que uno usa UICollectionViewFlowLayout.

Resulta que iOS 11 ha agregado una propiedad UICollectionViewFlowLayout a UICollectionViewFlowLayout . La documentación oficial en este momento carece de una descripción, sin embargo, los encabezados lo describen como

El límite de referencia que las secciones de las inserciones se definirán como relativas a. El valor predeterminado es .fromContentInset .

NOTA: El contenido del contenido siempre se respetará como mínimo. Por ejemplo, si la sectionInsetReference es igual a .fromSafeArea , pero el recuadro de contenido ajustado es mayor que la combinación del área segura y las inserciones de sección, el contenido de la sección se alineará con el recuadro de contenido.

Los posibles valores son

@available(iOS 11.0, *) public enum UICollectionViewFlowLayoutSectionInsetReference : Int { case fromContentInset case fromSafeArea case fromLayoutMargins }

y establecerlo en .fromSafeArea produce los resultados deseados, es decir, cuando inicialmente está en orientación vertical:

luego, cuando se gira hacia el paisaje, las celdas se insertan de manera que estén completamente dentro del área segura:

... SIN EMBARGO, actualmente hay un error, y cuando se gira de nuevo a retrato después de que la vista ha estado en el paisaje, continúa actuando como si los conjuntos de seguridades de izquierda / derecha estuvieran configurados en los valores de paisaje:

He archivado un radar ( rdar: // 34491993 ) con respecto a este problema.


Gracias a arriba por ayuda. Para mi SubClass UICollectionViewController, agregué lo siguiente para viewDidLoad () (Swift 3):

if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout { if #available(iOS 11.0, *) { flowLayout.sectionInsetReference = .fromSafeArea } }


Teniendo el mismo problema Esto funcionó para mí:

override func viewDidLoad() { if #available(iOS 11.0, *) { collectionView?.contentInsetAdjustmentBehavior = .always } }

La documentación para el caso .always enum dice:

Siempre incluya las inserciones de área segura en el ajuste del contenido.

Esta solución funciona correctamente también en el caso de que se gire el teléfono.