En una vertical UICollectionView
,
¿Es posible tener celdas de ancho completo , pero permitir que la altura dinámica sea controlada por el diseño automático ?
Esto me parece quizás la "pregunta más importante en iOS sin una respuesta realmente buena".
Importante:
Tenga en cuenta que en el 99% de los casos, para lograr celdas de ancho completo + altura dinámica de diseño automático, simplemente use una vista de tabla. Es fácil.
Entonces, ¿cuál es un ejemplo de dónde necesita una vista de colección?
Las vistas de colección son increíblemente más poderosas que las vistas de tabla.
Un ejemplo sencillo en el que realmente tiene que usar una vista de colección para lograr celdas de ancho completo + altura dinámica de diseño automático:
Si anima entre dos diseños en una vista de colección. Por ejemplo, entre un diseño de 1 y 2 columnas, cuando el dispositivo gira.
Ese es un modismo común y normal en iOS. Desafortunadamente, solo se puede lograr resolviendo el problema planteado en este QA. : - /
fuente
SpringDamping
yinitialSpringVelocity
) en la celda de la tabla ... eche un vistazo a esta lista hinchable usando tableView ,,,, pastebin.com/pFRQhkrX puede animar laTableViewCell
tabla en elwillDisplayCell:(UITableViewCell *)cell
método delgate @Fattie puede aceptar la respuesta que resolvió su problema para ayudar a otros que buscan el mismo problemaRespuestas:
1. Solución para iOS 13+
Con Swift 5.1 y iOS 13, puede usar objetos de diseño de composición para resolver su problema.
El siguiente código de muestra completo muestra cómo mostrar varias líneas
UILabel
dentro de ancho completoUICollectionViewCell
:CollectionViewController.swift
HeaderView.swift
CustomCell.swift
Pantalla esperada:
2. Solución para iOS 11+
Con Swift 5.1 y iOS 11, puede
UICollectionViewFlowLayout
crear una subclase y establecer suestimatedItemSize
propiedad enUICollectionViewFlowLayout.automaticSize
(esto le dice al sistema que desea lidiar con el tamaño automáticoUICollectionViewCell
). Luego tendrá que anularlayoutAttributesForElements(in:)
ylayoutAttributesForItem(at:)
para establecer el ancho de las celdas. Por último, tendrá que anular elpreferredLayoutAttributesFitting(_:)
método de su celda y calcular su altura.El siguiente código completo muestra cómo mostrar varias líneas
UILabel
dentro de ancho completoUIcollectionViewCell
(restringido porUICollectionView
el área segura yUICollectionViewFlowLayout
los insertos):CollectionViewController.swift
CustomFlowLayout.swift
HeaderView.swift
CustomCell.swift
Aquí hay algunas implementaciones alternativas para
preferredLayoutAttributesFitting(_:)
:Pantalla esperada:
fuente
Problema
Está buscando una altura automática y también desea tener un ancho completo, no es posible obtener ambos en el uso
UICollectionViewFlowLayoutAutomaticSize
.Lo que desea hacer es usar
UICollectionView
lo que a continuación es la solución para usted.Solución
1. Si sólo tiene
UILabel
enCollectionViewCell
que establecer elnumberOfLines=0
y que calcula la altura esperada deUIlable
, pasar el los tres parametros2. Si
CollectionViewCell
solo contieneUIImageView
y si se supone que es dinámico en altura, entonces necesita obtener la altura deUIImage
(UIImageView
debe tenerAspectRatio
restricciones)3. Si contiene ambos, calcule su altura y súmelos.
1. Agregue
UICollectionViewDelegateFlowLayout
delegado en su viewController2. Implementar el método delegado
Espero que esto lo pueda ayudar.
fuente
return CGSize(width: view.frame.width/2, height: expectedHeight)
También tenga en cuenta el relleno que devolver el ancho, de lo contrario, dos celdas no cabrían en una sola fila.Hay dos formas de abordar este problema.
Una forma es darle al diseño de flujo de la vista de colección un tamaño estimado y calcular el tamaño de celda.
Nota: Como se menciona en los comentarios a continuación, a partir de iOS 10 ya no es necesario proporcionar un tamaño estimado para activar la llamada a una celda
func preferredLayoutAttributesFitting(_ layoutAttributes:)
. Anteriormente (iOS 9) requería que proporcionara un tamaño estimado si deseaba consultar una celda prefferedLayoutAttributes.(asumiendo que está utilizando guiones gráficos y la vista de colección está conectada a través de IB)
Para celdas simples, eso suele ser suficiente. Si el tamaño sigue siendo incorrecto, en la celda de la vista de colección puede anularfunc preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes
, lo que le dará un mayor control sobre el tamaño de la celda. Nota: aún deberá darle al diseño de flujo un tamaño estimado .Luego anule
func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes
para devolver el tamaño correcto.Alternativamente, en su lugar, puede usar una celda de tamaño para calcular el tamaño de la celda en el
UICollectionViewDelegateFlowLayout
.Si bien estos no son ejemplos perfectos listos para la producción, deberían ayudarlo a comenzar en la dirección correcta. No puedo decir que esta sea la mejor práctica, pero me funciona, incluso con celdas bastante complejas que contienen varias etiquetas, que pueden o no ajustarse a varias líneas.
fuente
preferredLayoutAttributesFitting
. Luego agregué una restricción propia en dicha función, uniéndome a la dimensión fija de EstimatedItemSize, FWIW, vea mi respuesta a continuación.Encontré una solución bastante fácil para ese problema: dentro de mi CollectionViewCell obtuve un UIView () que en realidad es solo un fondo. Para obtener el ancho completo, simplemente establezco los siguientes anclajes
La "magia" ocurre en la primera línea. Configuré el widthAnchor dinámicamente al ancho de la pantalla. También es importante restar las inserciones de su CollectionView. De lo contrario, la celda no aparecerá. Si no desea tener esa vista de fondo, simplemente hágalo invisible.
FlowLayout utiliza la siguiente configuración
El resultado es una celda de tamaño de ancho completo con altura dinámica.
fuente
¡¡¡TRABAJANDO!!! Probado en IOS: 12.1 Swift 4.1
Tengo una solución muy simple que simplemente funciona sin romper restricciones.
Mi ViewControllerClass
Clase CustomCell:
El ingrediente principal es el systemLayoutSizeFitting función en Customcell. Y también tenemos que establecer el ancho de la vista dentro de la celda con restricciones.
fuente
Tienes que agregar restricción de ancho a CollectionViewCell
fuente
Conjunto
estimatedItemSize
de su diseño de flujo:Defina una restricción de ancho en la celda y configúrela para que sea igual al ancho de la supervista:
Ejemplo completo
Probado en iOS 11.
fuente
Personalmente, encontré las mejores formas de tener un UICollectionView donde AutoLayout determina el tamaño mientras que cada celda puede tener un tamaño diferente es implementar la función UICollectionViewDelegateFlowLayout sizeForItemAtIndexPath mientras se usa una celda real para medir el tamaño.
Hablé de esto en una de las publicaciones de mi blog.
Con suerte, este te ayudará a lograr lo que deseas. No estoy 100% seguro, pero creo que, a diferencia de UITableView, donde en realidad puede tener una altura de celdas completamente automática usando AutoLayout en combinación con
UICollectionView no tiene una forma de permitir que AutoLayout determine el tamaño porque UICollectionViewCell no necesariamente llena todo el ancho de la pantalla.
Pero aquí hay una pregunta para usted : si necesita celdas de ancho de pantalla completo, ¿por qué se molesta en usar UICollectionView sobre un UITableView antiguo que viene con las celdas de tamaño automático?
fuente
Según mi comentario sobre la respuesta de Eric, mi solución es muy similar a la suya, pero tuve que agregar una restricción en favoriteSizeFor ... para restringir a la dimensión fija.
Esta pregunta tiene varios duplicados, la respondí en detalle aquí y proporcioné una aplicación de muestra funcional aquí.
fuente
No estoy seguro si esto califica como una "muy buena respuesta", pero es lo que estoy usando para lograrlo. Mi diseño de flujo es horizontal y estoy tratando de ajustar el ancho con el diseño automático, por lo que es similar a su situación.
Luego, en el controlador de vista donde se modifica la restricción de diseño automático, disparo una NSNotification.
En mi subclase UICollectionView, escucho esa notificación:
e invalidar el diseño:
Esto hace
sizeForItemAt
que se vuelva a llamar utilizando el nuevo tamaño de la vista de colección. En su caso, debería poder actualizarse dadas las nuevas restricciones disponibles en el diseño.fuente
En su
viewDidLayoutSubviews
, establezca elestimatedItemSize
ancho completo (el diseño se refiere al objeto UICollectionViewFlowLayout):En su celda, asegúrese de que sus restricciones toquen tanto la parte superior como la inferior de la celda (el siguiente código usa Cartografía para simplificar la configuración de las restricciones, pero puede hacerlo con NSLayoutConstraint o IB si lo desea):
¡Voila, sus células ahora crecerán automáticamente en altura!
fuente
Ninguna de las soluciones me funcionó, ya que necesito un ancho dinámico para adaptarme al ancho de los iPhones.
fuente
Desde iOS 10, tenemos una nueva API en diseño de flujo para hacer eso.
Todo lo que tiene que hacer es configurar tu
flowLayout.estimatedItemSize
a una nueva constante,UICollectionViewFlowLayoutAutomaticSize
.Fuente
fuente
AutoLayout se puede utilizar para ajustar automáticamente el tamaño de las celdas en CollectionView en 2 sencillos pasos:
flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
collectionView(:cellForItemAt:)
para limitar el ancho de contentView al ancho de collectionView.Eso es todo, obtendrás el resultado deseado. Consulte las siguientes esencias para obtener el código completo:
Referencia / Créditos:
Captura de pantalla:
fuente
Tienes que heredar la clase UICollectionViewDelegateFlowLayout en tu collectionViewController. Luego agrega la función:
Con eso, tiene el tamaño de ancho del ancho de la pantalla.
Y ahora tiene un collectionViewController con filas como tableViewController.
Si desea que el tamaño de la altura de cada celda sea dinámicamente, tal vez debería crear celdas personalizadas para cada celda que necesite.
fuente