2013-06-04 14 views
42

Mam UICollectionViewController, który używa standardu UICollectionViewFlowLayout do wyświetlania pojedynczej pionowej kolumny komórek. Próbuję utworzyć animację rozwijania/zwijania w komórce po dotknięciu komórki. Używam następujący kod do osiągnięcia tego celu:UICollectionView Animacja zmiany rozmiaru komórki powoduje niepożądane zachowanie.

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath (NSIndexPath *)indexPath 
{ 
    [self.feedManager setCurrentlySelectedCellIndex:indexPath.item]; 
    [self.collectionView performBatchUpdates:nil completion:nil]; 
} 

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    //Return the size of each cell to draw 
    CGSize cellSize = (CGSize) { .width = 320, .height = [self.feedManager heightForCellAtIndexPath:indexPath] }; 
    return cellSize; 
} 

Nieruchomość „selectedCellIndex” na moim zarządzającego obiektem opowiada model danych powrotu rozszerzoną lub zwinięty rozmiaru wewnątrz heightForCellAtIndexpath:

[self.collectionView performBatchUpdates:nil completion:nil]; 

wtedy performBatchUpdates:completiong: Metoda animuje ten rozmiar ładnie się zmienia. Jednak! Gdy animacja się pojawi, rozwijająca się komórka może spowodować, że częściowo widoczna komórka na dole ekranu zniknie z ekranu.

Jeśli tak jest, a następnie zwijam tę komórkę, komórka teraz poza ekranem zostanie przyciągnięta do starej pozycji bez animacji, podczas gdy wszystkie inne widoczne komórki będą animowane zgodnie z potrzebami. Moja intuicja mówi, że jest to prawidłowe zachowanie, ponieważ komórka jest poza ekranem podczas animacji zwijania i nie jest uwzględniana w procesie renderowania animacji. Moje pytanie brzmi: jak temu zapobiec?

Wolałbym wszystkie komórki animować razem, niezależnie od tego, czy są poza ekranem, czy nie. jakieś pomysły?

+0

Znalazłem bardzo podobny problem podczas przeglądania http://stackoverflow.com/questions/13698275/uicollectionview-moveitematindexpathtoindexpath-issues-moving-items-not-on-scr –

+0

Wygląda na to, że ponownie wykorzystywane komórki stają na drodze animacji, ponieważ komórka poza ekranem jest oznaczana jako gotowa do ponownego użycia. Jakieś przemyślenia na temat zapobiegania umieszczaniu komórki w celu ponownego użycia? –

+0

Mam dokładnie ten sam problem i naprawdę podoba mi się rozwiązanie, nawet jeśli to rozwiązanie jest numerem radaru! – jrturton

Odpowiedz

27

To jest błąd UICollectionViewFlowLayout, ale istnieje obejście problemu. Problem polega na tym, że atrybuty zwracane przez initialLayoutAttributesForAppearingItemAtIndexPath: mają niewłaściwe ramki. W szczególności mają one ramy ostatecznej pozycji na ekranie, a nie początkowej pozycji poza ekranem. Trzeba tylko zastąpić tę metodę i zwrócić poprawne ramki. Podstawowa struktura override będzie wyglądać mniej więcej tak:

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath 
{ 
    UICollectionViewLayoutAttributes *pose = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath]; 
    if (<test for incorrect frame>) { 
     CGRect frame = pose.frame; 
     frame.origin.y = <calculate correct frame>; 
     pose.frame = frame; 
    } 
    return pose; 
} 

będzie odpowiedzialna za identyfikację scenariuszy, w których należy dostosować ramy, co może obejmować utrzymywanie własnego stanu wewnętrznego. Nie przepracowałem tej logiki, ale wykonałem prymitywny test i udało mi się uzyskać płynną animację.

Uogólniam, to jest moje doświadczenie, że tam jest UICollectionViewFlowLayout, a więc jest tak wiele błędów i jest tak wiele przypadków narożnych, z którymi można się uporać, jeśli masz przedmioty poruszające się i wyłączane w połączeniu z dowolnymi wstawkami, skreśleniami lub ruchami, które Zauważyłem, że łatwiej jest przetasować własne proste układy. Jeśli nie zamierzasz wprowadzać żadnych wstawek, usunięć ani przejść, przesłonięcie UICollectionViewFlowLayout może być najlepszym rozwiązaniem.

Daj mi znać, jeśli potrzebujesz więcej pomocy.

EDIT

Jeśli jesteś zainteresowany patrząc na 3-cim układu partyjnego, I open source mój układ niestandardowy siatki VCollectionViewGridLayout i dodał projekcie przykładowym wykazując gładka rozszerza wysokość komórek. Spróbuj uruchomić urządzenie Expand project. Istnieje również Sort & Filter project z animowanym sortowaniem i filtrowaniem. Oba projekty umożliwiają przełączanie między układem przepływu a układem siatki, aby można było zobaczyć poprawę.

+0

Twoja wskazówka na temat niewłaściwej ramki w 'initialLayout ...' była na miejscu. Przechowuję atrybuty komórek później niż moja wybrana komórka i porównuję je z ramkami zwróconymi w tej metodzie, zastępując w razie potrzeby. Moja istniejąca podklasa layoutu wykonuje już wiele pracy, ale przyjrzę się twojemu. – jrturton

+1

O tak, i mam 200 punktów! – jrturton

+0

@ TimothyMoose jak mam dołączyć VCollectionViewLayout i TLIndexPathTools do mojego projektu xcode? Właśnie dodałem pliki VCollectionViewLayout.h, VCollectionViewLayout.m i przeciągnij/upuść plik projektu TLIndexPathTools w grupie Frameworks mojego projektu i dodałem go jako Dependency i Linked Framework w fazie Build, ale pojawia się następujący błąd: Undefined symbols for architecture i386: " _OBJC_CLASS _ $ _ NSManagedObject ", do którego odwołuje się: objc-class-ref w libTLIndexPathTools.a (TLIndexPathDataModel.o) – ftartaggia

Powiązane problemy