2011-09-25 20 views
32

W jaki sposób anime - reloadData na UITableView? Źródło danych to UIFetchedResultsController, więc nie można odtwarzać z – insertSections:withRowAnimation:, – deleteSections:withRowAnimation: opakowanymi w – beginUpdates, – endUpdates.Animowane ponowne ładowanie na UITableView

EDYTOWANIE: Chcę zadzwonić pod numer - reloadData po odświeżeniu NSFetchedResultsController.

+3

duplikat to - http: // stackover flow.com/questions/419472/have-a-reloaddata-for-a-uitableview-animate-when-changing - dobra odpowiedź tam –

Odpowiedz

83

zrobiłem metoda kategorii.

- (void)reloadData:(BOOL)animated 
{ 
    [self reloadData]; 

    if (animated) { 

     CATransition *animation = [CATransition animation]; 
     [animation setType:kCATransitionPush]; 
     [animation setSubtype:kCATransitionFromBottom]; 
     [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 
     [animation setFillMode:kCAFillModeBoth]; 
     [animation setDuration:.3]; 
     [[self layer] addAnimation:animation forKey:@"UITableViewReloadDataAnimationKey"]; 

    } 
} 
+0

Ładne rozwiązanie, jeśli potrzebujesz niestandardowej animacji – voromax

+0

Amazing rozwiązanie!! – Jason

+0

Niesamowite rozwiązanie! Mam tylko jedną rzecz do dodania.W moim przypadku wystąpiły problemy powodujące, że TableView zanim reloadData przewinął się na sam dół, więc gdy animacja się zdarzyła, wkręciła wszystkie komórki i ramkę tabeli. Mogłabym go rozwiązać, upewniając się, że tableView został przewinięty do samego końca przed ponownym wczytaniem danych: [self scrollRectToVisible: CGRectMake (0, 0, 1, 1) animowany: NO]; – Pauls

9

Nie można animować reloadData. Będziesz musiał użyć metod wyświetlania tabeli, aby uczynić go animowanym.

Jest to całkiem proste, gdy używasz NSFetchedResultsController. Dokumentacja dla NSFetchedResultsControllerDelegate zawiera zestaw przykładowych metod, które po prostu trzeba dostosować do własnego kodu:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
    [self.tableView beginUpdates]; 
} 


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo 
    atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { 

    switch(type) { 
     case NSFetchedResultsChangeInsert: 
      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] 
          withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] 
          withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject 
    atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type 
    newIndexPath:(NSIndexPath *)newIndexPath { 

    UITableView *tableView = self.tableView; 

    switch(type) { 

     case NSFetchedResultsChangeInsert: 
      [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeUpdate: 
      [self configureCell:[tableView cellForRowAtIndexPath:indexPath] 
        atIndexPath:indexPath]; 
      break; 

     case NSFetchedResultsChangeMove: 
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
      [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
    [self.tableView endUpdates]; 
} 
+1

Przykro mi, że nie wspomniałem, że potrzebuję przeładować dane tabeli po "NSFetchedResultsController" . Myślę, że można to zrobić za pomocą animacji 'CALayer' na całym' UITableView' ... Coś jak powielona warstwa widoku tabeli, ponowne pobieranie, przeładowanie danych, animacja warstwy off ... – user500

27

Można zrobić podstawowe animacji reLoadData używając:

// Reload table with a slight animation 
[UIView transitionWithView:tableViewReference 
        duration:0.5f 
        options:UIViewAnimationOptionTransitionCrossDissolve 
       animations:^(void) { 
    [tableViewReference reloadData]; 
} completion:NULL]; 
+0

Przy każdej innej zmianie dane widoku tabeli nie są ponownie ładowane, dopóki nie rozpoczniesz przewijania. Każdy pomysł, dlaczego? –

+1

Podczas aktualizowania tabeli spoza głównego przepływu tabela może nie zostać automatycznie zaktualizowana. W takich przypadkach możesz użyć: [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; – Vincent

+0

Czy to działa w bloku animacji? –

5

I stworzył metodę UITableView kategorii w oparciu o rozwiązania firmy this link.

Należy ponownie załadować wszystkie sekcje tabeli. Możesz grać z opcjami UITableViewRowAnimation dla różnych efektów animacji.

- (void)reloadData:(BOOL)animated 
{ 
    [self reloadData]; 

    if (animated) 
    { 
     [self reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.numberOfSections)] withRowAnimation:UITableViewRowAnimationBottom]; 
    } 
} 
5
typedef enum { 
    UITableViewRowAnimationFade, 
    UITableViewRowAnimationRight, 
    UITableViewRowAnimationLeft, 
    UITableViewRowAnimationTop, 
    UITableViewRowAnimationBottom, 
    UITableViewRowAnimationNone, 
    UITableViewRowAnimationMiddle, 
    UITableViewRowAnimationAutomatic = 100 
} UITableViewRowAnimation; 

i metoda:

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; 
14

Możesz po prostu zadzwonić do tej linii, jeśli chcesz odświeżyć całą tabelę z animacją:

NSRange range = NSMakeRange(0, [self numberOfSectionsInTableView:self.tableView]); 
NSIndexSet *sections = [NSIndexSet indexSetWithIndexesInRange:range]; 
[self.tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationFade]; 
+0

Nice! Szukałem czystego rozwiązania ten jest dla tych, którzy nie chcą zadzwonić do brute reloadData .... – DogCoffee

1

może chcesz użyj:

Objective-C

/* Animate the table view reload */ 
[UIView transitionWithView:self.tableView 
        duration:0.35f 
        options:UIViewAnimationOptionTransitionCrossDissolve 
       animations:^(void) 
{ 
     [self.tableView reloadData]; 
} 
       completion:nil]; 

Swift opcje

UIView.transitionWithView(tableView, 
          duration:0.35, 
          options:.TransitionCrossDissolve, 
          animations: 
{() -> Void in 
    self.tableView.reloadData() 
}, 
          completion: nil); 

Animacja:

TransitionNone TransitionFlipFromLeft TransitionFlipFromRight TransitionCurlUp TransitionCurlDown TransitionCrossDissolve TransitionFlipFromTop TransitionFlipFromBottom

Reference

Powiązane problemy