Actualizado para Swift 5
preferredLayoutAttributesFittingAttributes
renombrado preferredLayoutAttributesFitting
y usar dimensionamiento automático
Actualizado para Swift 4
systemLayoutSizeFittingSize
renombrado a systemLayoutSizeFitting
Actualizado para iOS 9
Después de ver que mi solución GitHub se rompió en iOS 9, finalmente tuve el tiempo para investigar el problema por completo. Ahora he actualizado el repositorio para incluir varios ejemplos de diferentes configuraciones para celdas de tamaño propio. Mi conclusión es que las células auto dimensionantes son geniales en teoría pero desordenadas en la práctica. Una palabra de precaución al proceder con las células auto dimensionantes.
TL; DR
Mira mi proyecto GitHub
Las celdas de tamaño automático solo son compatibles con el diseño de flujo, así que asegúrese de que eso es lo que está utilizando.
Hay dos cosas que debe configurar para que las celdas de tamaño automático funcionen.
1. Establecer estimatedItemSize
enUICollectionViewFlowLayout
El diseño del flujo se volverá dinámico en la naturaleza una vez que configure la estimatedItemSize
propiedad.
self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
2. Agregue soporte para dimensionar su subclase de celda
Esto viene en 2 sabores; Diseño automático o anulación personalizada de preferredLayoutAttributesFittingAttributes
.
Crear y configurar celdas con diseño automático
No voy a entrar en detalles sobre esto ya que hay un brillante publicación SO sobre la configuración de restricciones para una celda. Solo tenga cuidado de que Xcode 6 rompió un montón de cosas con iOS 7, por lo que, si es compatible con iOS 7, deberá hacer cosas como asegurarse de que autoresizingMask esté configurado en contentView de la celda y que los límites de contentView estén establecidos como los límites de la celda cuando la celda está cargada (es decir awakeFromNib
).
Lo que debe tener en cuenta es que su celda debe estar más seriamente restringida que una celda de vista de tabla. Por ejemplo, si desea que su ancho sea dinámico, su celda necesita una restricción de altura. Del mismo modo, si desea que la altura sea dinámica, necesitará una restricción de ancho para su celda.
Implementar preferredLayoutAttributesFittingAttributes
en su celda personalizada
Cuando se llama a esta función, su vista ya se ha configurado con contenido (es decir, cellForItem
se ha llamado). Suponiendo que sus restricciones se hayan establecido adecuadamente, podría tener una implementación como esta:
//forces the system to do one layout pass
var isHeightCalculated: Bool = false
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
//Exhibit A - We need to cache our calculation to prevent a crash.
if !isHeightCalculated {
setNeedsLayout()
layoutIfNeeded()
let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
var newFrame = layoutAttributes.frame
newFrame.size.width = CGFloat(ceilf(Float(size.width)))
layoutAttributes.frame = newFrame
isHeightCalculated = true
}
return layoutAttributes
}
NOTA En iOS 9, el comportamiento cambió un poco y podría causar fallas en su implementación si no tiene cuidado (vea más aquí ). Cuando implementaspreferredLayoutAttributesFittingAttributes
, debe asegurarse de que solo cambie el marco de sus atributos de diseño una vez. Si no hace esto, el diseño llamará a su implementación indefinidamente y finalmente se bloqueará. Una solución es almacenar en caché el tamaño calculado en su celda e invalidarlo cada vez que reutilice la celda o cambie su contenido como lo he hecho con elisHeightCalculated
propiedad.
Experimenta tu diseño
En este punto, debería tener celdas dinámicas "funcionales" en su collectionView. Todavía no he encontrado suficiente la solución lista para usar durante mis pruebas, así que siéntase libre de comentar. Todavía se siente comoUITableView
gana la batalla por el tamaño dinámico en mi humilde opinión.
Advertencias
Tenga en cuenta que si está utilizando celdas prototipo para calcular el tamaño estimado del artículo, esto se romperá si su XIB usa clases de tamaño . La razón de esto es que cuando carga su celda desde un XIB, su clase de tamaño se configurará con Undefined
. Esto solo se romperá en iOS 8 y superior, ya que en iOS 7 la clase de tamaño se cargará en función del dispositivo (iPad = Regular-Any, iPhone = Compact-Any). Puede establecer el tamaño estimado del artículo sin cargar el XIB, o puede cargar la celda desde el XIB, agregarlo a la colecciónView (esto establecerá la colección de caracteres), realizar el diseño y luego eliminarlo de la supervista. Alternativamente, también podría hacer que su celda anule el traitCollection
getter y devuelva los rasgos apropiados. Tu decides.
Avíseme si me perdí algo, espero haber ayudado y buena suerte codificando