custom ios uicollectionview uicollectionviewlayout

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



uicollectionview layout (2)

Así que este es un problema interesante que encontramos con UICollectionViewFlowLayout en iOS 10 (todavía es un problema en 11) y que usa UICollectionViewFlowLayoutAutomaticSize para el valor estimado del artículo.

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

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

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 adicionales de encabezado y pie de página? Si agrego un tamaño al estimadoItemSize, entonces parece que funciona, pero quiero saber si hay un error en el uso de la nueva función iOS 10 o si lo estoy usando incorrectamente.

El error presentado con Apple tiene el ID: 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


Me encontré con el mismo problema. UICollectionViewFlowLayoutAutomaticSize no funciona para vistas suplementarias. Use UICollectionViewDelegateFlowLayout para dar el tamaño explícitamente. Es mejor calcular los tamaños y utilizar delegados, ya que los cálculos automáticos de tamaño causan retrasos, a veces.

use los métodos de delegación referenceSizeForHeaderInSection y referenceSizeForFooterInSection para dar el encabezado y el tamaño del pie de página explícitamente.


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

Debe anular la func invalidationContext(forPreferredLayoutAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes: UICollectionViewLayoutAttributes) y realizar una invalidación de vista complementaria en él.

Ejemplo:

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

En el ejemplo anterior, estoy usando el contexto de invalidación provisto por UICollectionViewFlowLayout para invalidar la vista suplementaria del encabezado si se invalida la primera celda de la sección. También puede utilizar este método para la invalidación de pie de página.