Tengo que agregar un UICollectionView dentro de un UITableViewCell . El collectionView puede tener un número diferente de elementos. Por lo tanto, collectionView debería ajustarse correctamente dentro de tableView .
He implementado esto dentro de mi Proyecto: https://github.com/vishalwaka/DynamicCollectionViewInsideTableViewCell
En mi caso, la altura de la celda no se ajusta después de establecer la altura de collectionView .
¿Cómo puedo configurar collectionView para que no se pueda desplazar y también mostrar todo el contenido dentro de tableviewcell ?
Cree una vista de collectionView dentro de UITableViewCell con una restricción de altura inicial, final, superior, inferior, como esta:
Ahora, en su clase tableViewCell , cree un NSKeyValueObserver y agréguelo en la propiedad UICollectionView de UICollectionView y asigne cambios de contentSize a la restricción de altura de collectionView.
class FormCollectionTableViewCell: UITableViewCell{ var collectionViewObserver: NSKeyValueObservation? override func awakeFromNib() { super.awakeFromNib() addObserver() } override func layoutSubviews() { super.layoutSubviews() layoutIfNeeded() } func addObserver() { collectionViewObserver = collectionView.observe(\.contentSize, changeHandler: { [weak self] (collectionView, change) in self?.collectionView.invalidateIntrinsicContentSize() self?.collectionViewHrightConstarint.constant = collectionView.contentSize.height self?.layoutIfNeeded() }) } deinit { collectionViewObserver = nil } }Y en su clase viewController use el siguiente código:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() tableView.reloadData() } Ahora, su vista de tabla tendrá una vista de colección con altura dinámica. No olvide desactivar el desplazamiento de UICollectionView y ajustar su flujo.
Cree la siguiente subclase de una vista de colección:
class IntrinsicSizeCollectionView: UICollectionView { required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.setup() } override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) { super.init(frame: frame, collectionViewLayout: layout) self.setup() } override func layoutSubviews() { super.layoutSubviews() if !self.bounds.size.equalTo(self.intrinsicContentSize) { self.invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize { get { let intrinsicContentSize = self.contentSize return intrinsicContentSize } } func setup() { self.isScrollEnabled = false self.bounces = false }Agregue collectionView a tableViewCell y establezca sus restricciones de inicio, final, superior e inferior a los límites de la celda. También establezca el tamaño intrínseco como en la captura de pantalla.
El tamaño de tableViewCell debe establecerse en la dimensión UITableViewAutomatic y también debe establecerse un valor estimado para esta celda en el origen de datos de TableView.
Eso debería ser todo.
Después de verificar su proyecto, le sugiero que use un enfoque ligeramente diferente.
Después de actualizar el modelo, puede preguntarle al diseño de la vista de la colección cuál será el nuevo tamaño del contenido ( collectionViewLayout.collectionViewContentSize ). Luego actualiza la constante de restricción de altura.
Entonces, deberías:
contentSize de contenidoEsta modificación en su proyecto debería lograr esto:
// Remove the content size observing logic. func configureForVehicle(_ vehicle: Vehicle, selectedHouseType: String) { self.vehicle = vehicle applianceCollectionView.reloadData() // Set the height constraint to the new value, found in the layout's content size info. // Since the model (self.vehicle) was already updated, the layout will return the new content size. // Because this is all happening while the cell is being reloaded, the cell will also resize properly. // You don't need to perform any other setNeedsLayout/layoutIfNeeded calls. self.applianceCollectionViewHeightConstraint.constant = applianceCollectionView.collectionViewLayout.collectionViewContentSize.height } Tenga en cuenta el comentario acerca de no necesitar llamadas de actualización de diseño adicionales. Solo llamar a tableView.reloadRows(at: [indexPath], with: .automatic) debería ser suficiente. Las actualizaciones de diseño innecesarias pueden causar un impacto en el rendimiento.
Como nota al margen, hay otro enfoque que puede usar si desea animar el cambio de altura sin recargar la celda . En este caso, deberá mantener/encontrar una referencia a la celda que desea actualizar y luego hacer lo siguiente:
tableView.beginUpdates(); tableView.endUpdates() . Esto hace que TableView vuelva a diseñar sus celdas y anime los cambios de altura.De la documentación de beginUpdates() :
También puede usar este método seguido del método endUpdates() para animar el cambio en las alturas de las filas sin recargar la celda. Este grupo de métodos debe concluir con una invocación de endUpdates().