2015-05-01 9 views
7

W widoku dodatkowym UICollectionView (nagłówek) mam etykietę wielowierszową, którą chcę obcinać do 3 linii.Dynamiczna zmiana rozmiaru dodatkowego widoku UICollectionView (zawierającego multilinię UILabel)

enter image description here

Gdy użytkownik kliknie w dowolnym miejscu na nagłówku (uzupełniającym) zdaniem, chcę przełączyć UILabel do 0 linie tak, wszystkie wyświetlacze tekstowe i odpowiednio rośnie wysokość uzupełniające widoku danych, w CollectionView za (najlepiej animowane). Oto, co dzieje się po dotknięciu nagłówka:

enter image description here

Oto mój kod do tej pory:

// 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)); 
} 

Kiedy loguję height na koniec layoutSubviews, jego wartość to 149, natomiast etykieta jest obcięty i numberOfLines jest ustawiona na 3. Po dotknięciu nagłówkaView, ustawienie numberOfLines na 0 i wymuszenie przejścia układu, wysokość zostanie zapisana jako 163,5. Wspaniały!

Jedynym problemem jest to, że cały headerView nie rośnie, a komórki nie są zmniejszane.

Jak mogę dynamicznie zmieniać wysokość mojego dodatkowego widoku kolekcji (najlepiej animowanego)?

Jestem świadomy UICollectionViewFlowLayout za headerReferenceSize i collectionView:layout:referenceSizeForHeaderInSection:, ale nie jestem pewien, jak bym ich użył w tej sytuacji.

Odpowiedz

4

Mam coś działającego, ale muszę przyznać, że czuje się kludgy. Czuję, że można to osiągnąć dzięki standardowemu API CollectionView (i powiązanym elementom) + zahaczeniu o standardowe unieważnienie układu/wyświetlania, ale po prostu nie mogłem go uruchomić.

Jedyna rzecz, która zmieniłaby rozmiar mojego widoku nagłówka, to ustawienie układu przepływu w widoku mojej kolekcji: headerReferenceSize. Niestety, nie mam dostępu do mojego widoku kolekcji lub jego układu przepływu z mojego wystąpienia UICollectionReusableView, więc musiałem stworzyć metodę delegowania, aby przekazać prawidłową wysokość z powrotem.

Oto co mam teraz:

// 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]; 
    }]; 
} 

Tak jak mówiłem, nie rozwiązanie szukałem, ale mimo to roztwór roboczy.

+0

Dzięki stary po 1 lata później zaoszczędziłeś mój czas w Swift 3 dzięki temu podejściu. Nie całkowicie, ale dodałem jeszcze inne rzeczy na tej bazie :) +1 – tobeiosdev

0

Wpadłem na ten sam problem niż ty, więc zastanawiałem się: czy kiedykolwiek dostałeś rozwiązanie bez efektu przenikania, o którym wspomniałeś w próbce kodu ?. Moje podejście było prawie takie samo, więc mam ten sam problem. Chociaż jeden dodatkowy komentarz: udało mi się wdrożyć rozwiązanie bez konieczności delegacji: Co zrobiłem było z „MyHeaderReusableView.m” Można odwoływać się UICollectionView (a zatem UICollectionViewLayout) przez:

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

} 
Powiązane problemy