iOS 10/11 UICollectionViewFlowLayout usando UICollectionViewFlowLayoutAutomaticSize da como resultado una vista suplementaria del pie de página desalineada

Entonces, este es un tema interesante que encontramos con UICollectionViewFlowLayout en iOS 10 (sigue siendo un problema en 11) y el uso de UICollectionViewFlowLayoutAutomaticSize para estimatedItemSize.

Hemos encontrado que el uso de UICollectionViewFlowLayoutAutomaticSize para los resultados estimatedItemSize en la vista suplementaria del pie de página que flota sobre las pocas celdas inferiores. (Rojo / Rosa es el encabezado, Verde es el pie de página).

UICollectionViewFlowLayoutAutomaticSize problema introduzca la descripción de la imagen aquí

Aquí está el código de VC de una aplicación de ejemplo:

 import UIKit class ViewController: UIViewController { // MARK: Properties let texts: [String] = [ "This is some text", "This is some more text", "This is even more text" ] // MARK: Outlets @IBOutlet var collectionView: UICollectionView! { didSet { self.collectionView.backgroundColor = .orange } } // MARK: Lifecycle override func viewDidLoad() { super.viewDidLoad() // Layout let layout = UICollectionViewFlowLayout() layout.scrollDirection = .vertical if #available(iOS 10.0, *) { layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize } else { layout.estimatedItemSize = CGSize(width: self.collectionView.bounds.width, height: 50) } self.collectionView.collectionViewLayout = layout // Register Cells self.collectionView.register(UINib(nibName: "TextCell", bundle: nil), forCellWithReuseIdentifier: String(describing: TextCell.self)) self.collectionView.register(UINib(nibName: "SectionHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: String(describing: SectionHeader.self)) self.collectionView.register(UINib(nibName: "SectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: String(describing: SectionFooter.self)) self.collectionView.reloadData() } } // MARK: - UICollectionViewDelegateFlowLayout Methods extension ViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { return CGSize(width: self.collectionView.bounds.width, height: 90) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: self.collectionView.bounds.width, height: 90) } } // MARK: - UICollectionViewDataSource Methods extension ViewController: UICollectionViewDataSource { public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return self.texts.count } func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 } public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: TextCell.self), for: indexPath) if let textCell = cell as? TextCell { let text = self.texts[indexPath.row] textCell.configure(text: text) } return cell } func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { switch kind { case UICollectionElementKindSectionHeader: return collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: String(describing: SectionHeader.self), for: indexPath) case UICollectionElementKindSectionFooter: return collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: String(describing: SectionFooter.self), for: indexPath) default: return UICollectionReusableView() } } } // MARK: - UICollectionViewDelegate Methods extension ViewController: UICollectionViewDelegate { } 

¿Alguien ha logrado que UICollectionViewFlowLayoutAutomaticSize funcione en iOS 10 con vistas complementarias de encabezado y pie de página? Si agrego un tamaño a the estimatedItemSize, parece que funciona, pero quiero saber si hay un error al usar la nueva característica de iOS 10 o si lo uso incorrectamente.

El error archivado con Apple tiene la identificación: 28843116

ACTUALIZACIÓN : Esto todavía parece ser un problema en 10.3 Beta 1

ACTUALIZACIÓN 2 : Esto todavía parece ser un problema en iOS 11 Beta 1

UICollectionViewFlowLayout admite el layout automático para celdas muy bien, PERO no lo admite para vistas adicionales. Cada vez que el código de layout automático actualiza el marco de la celda, no hace nada con encabezados y pies de página. Por lo tanto, debe indicar el layout que debería invalidar los encabezados y pies de página. ¡Y hay un método para esto!

Debe anular UICollectionViewLayout 's func invalidationContext(forPrefernetworkingLayoutAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes: UICollectionViewLayoutAttributes) y realizar una invalidation de vista suplementaria en ella.

Ejemplo:

 override open func invalidationContext(forPrefernetworkingLayoutAttributes prefernetworking: UICollectionViewLayoutAttributes, withOriginalAttributes original: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutInvalidationContext { let context: UICollectionViewLayoutInvalidationContext = super.invalidationContext( forPrefernetworkingLayoutAttributes: prefernetworking, withOriginalAttributes: original ) let indexPath = prefernetworking.indexPath if indexPath.item == 0 { context.invalidateSupplementaryElements(ofKind: UICollectionElementKindSectionHeader, at: [indexPath]) } return context } 

En el ejemplo anterior, uso el context de invalidation proporcionado por UICollectionViewFlowLayout para invalidar la vista complementaria del encabezado si la primera celda en la sección se invalidó. También puede usar este método para la invalidation del pie de página.

Me encontré con el mismo problema. UICollectionViewFlowLayoutAutomaticSize no funciona para vistas adicionales. Use UICollectionViewDelegateFlowLayout para dar el tamaño explícitamente. Es mejor calcular los tamaños y usar a los delegates, ya que los cálculos automáticos del tamaño ocasionan retrasos, a veces.

utilice los methods delegate referenceSizeForHeaderInSection y referenceSizeForFooterInSection para dar explícitamente el tamaño del encabezado y del pie de página.