2015-05-01 8 views
7

All'interno di una vista supplementare (intestazione) di UICollectionView, ho un'etichetta multilinea che desidero troncare su 3 righe.Ridimensiona dinamicamente la vista supplementare di UICollectionView (contenente le UILabel multilinea)

enter image description here

Quando l'utente tocca un punto qualsiasi dell'intestazione vista (complementare), che cambio l'UILabel a 0 linee così tutte visualizza il testo, e crescere Altezza della vista complementare del CollectionView conseguenza (preferibilmente animata). Ecco cosa succede dopo aver toccato l'intestazione:

enter image description here

Ecco il mio codice finora:

// 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.preferredMaxLayoutWidth = self.listTitle.frame.size.width; 
    self.listIntro.preferredMaxLayoutWidth = 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)); 
} 

Quando annoto height alla fine del layoutSubviews, il suo valore è 149, mentre l'etichetta viene troncato e numberOfLines è impostato su 3. Dopo aver toccato l'headerView, impostando numberOfLines su 0 e forzando un passaggio di layout, l'altezza viene registrata come 163.5. Grande!

L'unico problema è che l'intero headerView non cresce e le celle non vengono premute.

Come è possibile modificare dinamicamente l'altezza della vista complementare della mia collezioneView (preferibilmente animata)?

Sono a conoscenza di UICollectionViewFlowLayout's headerReferenceSize e collectionView:layout:referenceSizeForHeaderInSection: ma non sono sicuro di come li utilizzerei in questa situazione.

risposta

4

Ho qualcosa che funziona, ma lo ammetto, mi sembra nervoso. Credo che questo potrebbe essere ottenuto con l'API + standard CollectionView (e gli elementi associati) che si aggancia all'invalidazione di layout/display standard, ma non riuscivo a farlo funzionare.

L'unica cosa che avrebbe ridimensionato il mio headerView era impostare il layout di flusso della mia collezione view headerReferenceSize. Purtroppo, non riesco ad accedere alla mia vista raccolta o al layout del flusso dalla mia istanza di UICollectionReusableView, quindi ho dovuto creare un metodo delegato per ripristinare l'altezza corretta.

Ecco quello che ho adesso:

// in MyHeaderReusableView.m 
// 
// my UITapGestureRecognizer's action 
- (IBAction)onHeaderTap:(UITapGestureRecognizer *)sender 
{ 
    self.listIntro.numberOfLines = 0; 
} 

- (void)layoutSubviews 
{ 
    [super layoutSubviews]; 

    self.listTitle.preferredMaxLayoutWidth = self.listTitle.frame.size.width; 
    self.listIntro.preferredMaxLayoutWidth = 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]; 
    }]; 
} 

Come ho detto, non è la soluzione che stavo cercando, ma una soluzione di lavoro comunque.

+0

Grazie uomo dopo 1 anno dopo mi hai salvato il mio tempo in Swift 3 con questo approccio. Non totalmente ma ho aggiunto un altro elemento su questa base :) +1 – tobeiosdev

0

Mi sono imbattuto nello stesso problema di te, quindi mi stavo chiedendo: hai mai avuto una soluzione senza l'effetto di dissolvenza incrociata che hai menzionato nel codice di esempio ?. Il mio approccio era praticamente lo stesso, quindi ho lo stesso problema. Un commento aggiuntivo però: sono riuscito a implementare la soluzione, senza la necessità per la delega: Quello che ho fatto è stato da "MyHeaderReusableView.m" Si può fare riferimento al UICollectionView (e quindi, l'UICollectionViewLayout) da:

//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 

}