Cambia el tamaño dinámicamente de la vista suplementaria de UICollectionView (que contiene UILabel multilínea)

Dentro de la vista suplementaria (encabezado) de UICollectionView, tengo una label multilínea que quiero truncar en 3 líneas.

introduzca la descripción de la imagen aquí

Cuando el usuario pulsa en cualquier lugar de la vista del encabezado (complementario), quiero cambiar el UILabel a 0 líneas para que se muestre todo el text, y boost la altura de la vista complementaria de la colección de manera correspondiente (preferiblemente animada). Esto es lo que sucede después de tocar el encabezado:

introduzca la descripción de la imagen aquí

Aquí está mi código hasta ahora:

// MyHeaderReusableView.m // my gesture recognizer's action - (IBAction)onHeaderTap:(UITapGestureRecognizer *)sender { self.listIntro.numberOfLines = 0; // force -layoutSubviews to run again [self setNeedsLayout]; [self layoutIfNeeded]; } - (void)layoutSubviews { [super layoutSubviews]; self.listTitle.prefernetworkingMaxLayoutWidth = self.listTitle.frame.size.width; self.listIntro.prefernetworkingMaxLayoutWidth = self.listIntro.frame.size.width; [self layoutIfNeeded]; CGFloat height = [self systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; self.frame = ({ CGRect headerFrame = self.frame; headerFrame.size.height = height; headerFrame; }); NSLog(@"height: %@", @(height)); } 

Cuando logging la height al final de las layoutSubviews de layoutSubviews , su valor es 149 mientras que la label está truncada y el número de numberOfLines se establece en 3. Después de tocar el encabezadoView, estableciendo el número de líneas en 0 y forzando un pase de layout, la altura se registra como 163.5. ¡Estupendo!

El único problema es que todo el headerView no crece, y las celdas no son empujadas hacia abajo.

¿Cómo puedo cambiar dinámicamente la altura de la vista suplementaria de my collectionView (preferiblemente animada)?

Estoy al tanto de UICollectionViewFlowLayout's headerReferenceSize y collectionView:layout:referenceSizeForHeaderInSection: pero no estoy seguro de cómo los utilizaría en esta situación.

Tengo algo de trabajo, pero lo admito, se siente zambullida. Siento que esto podría lograrse con la API estándar CollectionView (y los elementos asociados) enganchándose a la invalidation estándar de layout / visualización, pero no pude lograr que funcione.

Lo único que cambiaría el tamaño de mi headerView fue establecer el encabezadoReferenceSize del layout de flujo de la vista de colección. Desafortunadamente, no puedo acceder a mi vista de colección ni a su layout de flujo desde mi instancia de UICollectionReusableView, así que tuve que crear un método de delegado para devolver la altura correcta.

Esto es lo que tengo ahora:

 // in MyHeaderReusableView.m // // my UITapGestureRecognizer's action - (IBAction)onHeaderTap:(UITapGestureRecognizer *)sender { self.listIntro.numberOfLines = 0; } - (void)layoutSubviews { [super layoutSubviews]; self.listTitle.prefernetworkingMaxLayoutWidth = self.listTitle.frame.size.width; self.listIntro.prefernetworkingMaxLayoutWidth = self.listIntro.frame.size.width; CGFloat height = [self systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; self.frame = ({ CGRect headerFrame = self.frame; headerFrame.size.height = height; headerFrame; }); if (self.resizeDelegate) { [self.resizeDelegate wanderlistDetailHeaderDidResize:self.frame.size]; } } // in my viewController subclass which owns the UICollectionView: - (void)wanderlistDetailHeaderDidResize:(CGSize)newSize { UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout; // this is the key line flowLayout.headerReferenceSize = newSize; // this doesn't look beautiful but it's the best i can do for now. I would love for just the bottom of the frame to animate down, but instead, all the contents in the header (the top labels) have a crossfade effect applied. [UIView animateWithDuration:0.3 animations:^{ [self.collectionView layoutIfNeeded]; }]; } 

Como dije, no la solución que estaba buscando, pero una solución de trabajo, no obstante.

Me encontré con el mismo problema que tú, así que me preguntaba: ¿Alguna vez has encontrado una solución sin el efecto crossfade que mencionas en el código de muestra ?. Mi enfoque fue prácticamente el mismo, así que tengo el mismo problema. Sin embargo, un comentario adicional: logré implementar la solución sin necesidad de delegación: lo que hice fue "MyHeaderReusableView.m" Puedes hacer reference a UICollectionView (y, por lo tanto, UICollectionViewLayout) mediante:

 //from MyHeaderReusableView.m if ([self.superview isKindOfClass:UICollectionView.class]) { //get collectionView reference UICollectionView * collectionView = (UICollectionView*)self.superview; //layout UICollectionViewFlowLayout * layout = (UICollectionViewFlowLayout *)collectionView.collectionViewLayout; //... perform the header size change }