it-swarm.com.de

Lassen Sie eine reloadData für eine UITableView beim Ändern animieren

Ich habe eine UITableView, die zwei Modi hat. Wenn wir zwischen den Modi wechseln, habe ich eine unterschiedliche Anzahl von Abschnitten und Zellen pro Abschnitt. Idealerweise würde es einige coole Animationen machen, wenn der Tisch wächst oder schrumpft.

Hier ist der Code, den ich ausprobiert habe, aber er tut nichts:

CGContextRef context = UIGraphicsGetCurrentContext(); 
[UIView beginAnimations:nil context:context]; 
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; 
[UIView setAnimationDuration:0.5]; 

[self.tableView reloadData];
[UIView commitAnimations];

Irgendwelche Gedanken, wie ich das machen könnte?

164
Chris Butler

Eigentlich ist es sehr einfach:

[_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];

Aus der Dokumentation :

Beim Aufruf dieser Methode fragt die Tabellensicht ihre Datenquelle nach neue Zellen für die angegebenen Abschnitte. Die Tabellenansicht animiert die Einfügen neuer Zellen in die alten Zellen.

384
dmarnel

Vielleicht möchten Sie verwenden:

Ziel c

[UIView transitionWithView: self.tableView
                  duration: 0.35f
                   options: UIViewAnimationOptionTransitionCrossDissolve
                animations: ^(void)
 {
      [self.tableView reloadData];
 }
                completion: nil];

Swift

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

Swift 3

UIView.transition(with: tableView,
                  duration: 0.35,
                  options: .transitionCrossDissolve,
                  animations: { self.tableView.reloadData() }) // left out the unnecessary syntax in the completion block and the optional completion parameter

Kein Ärger : D

Sie können auch eine beliebige UIViewAnimationOptionTransitions für coolere Effekte verwenden:

  • TransitionNone
  • TransitionFlipFromLeft
  • TransitionFlipFromRight
  • TransitionCurlUp
  • TransitionCurlDown
  • TransitionCrossDissolve
  • TransitionFlipFromTop
  • TransitionFlipFromBottom
229
Kenn Cal

Mehr Freiheit mit der CATransition-Klasse.

Es ist nicht auf das Verblassen beschränkt, sondern kann auch Bewegungen ausführen.


Zum Beispiel:

(nicht vergessen, QuartzCore zu importieren)

CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.fillMode = kCAFillModeForwards;
transition.duration = 0.5;
transition.subtype = kCATransitionFromBottom;

[[self.tableView layer] addAnimation:transition forKey:@"UITableViewReloadDataAnimationKey"];

Ändern Sie die type entsprechend Ihren Bedürfnissen, wie kCATransitionFade usw.

Implementierung in Swift:

let transition = CATransition()
transition.type = kCATransitionPush
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.fillMode = kCAFillModeForwards
transition.duration = 0.5
transition.subtype = kCATransitionFromTop
self.tableView.layer.addAnimation(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()

Referenz für CATransition

65
code ninja

Ich glaube, Sie können einfach Ihre Datenstruktur aktualisieren und dann:

[tableView beginUpdates];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView endUpdates];

Auch "withRowAnimation" ist nicht genau ein Boolean, sondern ein Animationsstil:

UITableViewRowAnimationFade,
UITableViewRowAnimationRight,
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone,
UITableViewRowAnimationMiddle
59

Bei allen diesen Antworten wird davon ausgegangen, dass Sie eine UITableView mit nur einem Abschnitt verwenden.

Um Situationen genau zu behandeln, in denen Sie mehr als einen Abschnitt haben, verwenden Sie Folgendes:

NSRange range = NSMakeRange(0, myTableView.numberOfSections);
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range];
[myTableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];

(Hinweis: Sie sollten sicherstellen, dass Sie mehr als 0 Abschnitte haben!)

Beachten Sie außerdem, dass Sie möglicherweise eine NSInternalInconsistencyException ausführen, wenn Sie versuchen, Ihre Datenquelle gleichzeitig mit diesem Code zu aktualisieren. In diesem Fall können Sie eine ähnliche Logik verwenden:

int sectionNumber = 0; //Note that your section may be different

int nextIndex = [currentItems count]; //starting index of newly added items

[myTableView beginUpdates];

for (NSObject *item in itemsToAdd) {
    //Add the item to the data source
    [currentItems addObject:item];

    //Add the item to the table view
    NSIndexPath *path = [NSIndexPath indexPathForRow:nextIndex++ inSection:sectionNumber];
    [myTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationAutomatic];
}

[myTableView endUpdates];
23
diadyne

Um dies zu erreichen, teilen Sie dem tableView mit, dass Zeilen und Abschnitte entfernt und hinzugefügt werden sollen

insertRowsAtIndexPaths:withRowAnimation:, deleteRowsAtIndexPaths:withRowAnimation:, insertSections:withRowAnimation: und deleteSections:withRowAnimation:

methoden von UITableView. Wenn Sie diese Methoden aufrufen, animiert die Tabelle die angeforderten Elemente in/out und ruft dann reloadData für sich selbst auf, damit Sie den Status nach dieser Animation aktualisieren können. Dieser Teil ist wichtig: Wenn Sie alles animieren, die von der dataSource der Tabelle zurückgegebenen Daten jedoch nicht ändern, werden die Zeilen nach Abschluss der Animation erneut angezeigt. 

Ihr Bewerbungsablauf wäre also:

[self setTableIsInSecondState:YES];

[myTable deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]];

Solange die dataSource-Methoden Ihrer Tabelle den korrekten neuen Satz von Abschnitten und Zeilen durch Prüfen von [self tableIsInSecondState] (oder was auch immer) zurückgeben, wird der gewünschte Effekt erzielt.

17
iKenndac

Ich kann die erste Antwort nicht kommentieren, aber eine schnelle Implementierung wäre: 

self.tableView.reloadSections([0], with: UITableViewRowAnimation.fade)

sie können im ersten Argument für reloadSections so viele Abschnitte hinzufügen, wie Sie aktualisieren möchten.

Weitere Animationen aus den Dokumenten: https://developer.Apple.com/reference/uikit/uitableviewrowanimation

fade Die eingefügten oder gelöschten Zeilen werden in die Tabellenansicht ein- oder ausgeblendet.

right Die eingefügte Zeile oder die eingefügten Zeilen werden von rechts eingezogen. Die gelöschte Zeile oder die gelöschten Zeilen werden nach rechts verschoben.

left Die eingefügte Zeile oder die eingefügten Zeilen werden von links eingezogen. Die gelöschte Zeile oder die gelöschten Zeilen werden nach links verschoben.

top Die eingefügte Zeile oder die eingefügten Zeilen werden von oben eingezogen. Die gelöschte Zeile oder die gelöschten Zeilen werden nach oben verschoben.

bottom Die eingefügte Zeile oder die eingefügten Zeilen werden von unten eingezogen. Die gelöschte Reihe oder die gelöschten Reihen werden nach unten verschoben.

case none Die eingefügten oder gelöschten Zeilen verwenden die Standardanimationen.

middle Die Tabellensicht versucht, die alten und neuen Zellen in dem Bereich zu zentrieren, den sie verwendet haben oder belegen werden. Verfügbar in iPhone 3.2.

automatic Die Tabellenansicht wählt einen geeigneten Animationsstil für Sie aus. (In iOS 5.0 eingeführt.)

16

Schnelle Implementierung:

let range = NSMakeRange(0, self.tableView!.numberOfSections())
let indexSet = NSIndexSet(indexesInRange: range)
self.tableView!.reloadSections(indexSet, withRowAnimation: UITableViewRowAnimation.Automatic)
9

Swift 4 Version für @dmarnel Antwort:

tableView.reloadSections(IndexSet(integer: 0), with: .automatic)
9
chengsam

Für Swift 4

tableView.reloadSections([0], with: UITableView.RowAnimation.fade)
2
Claus
CATransition *animation = [CATransition animation];
animation.duration = .3;
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[animation setDuration:.3];

[[_elementTableView layer] addAnimation:animation forKey:@"UITableViewReloadDataAnimationKey"];

[tableView reloadData];
1
Mayur Sardana

Animationen ohne reloadData () in Swift können wie folgt gemacht werden (ab Version 2.2):

tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove ?? 0

// Do your work here
while numOfCellsToRemove > 0 {
    // ...or here, if you need to add/remove the same amount of objects to/from somewhere
    indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
    numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()

falls Sie reloadData () nach dem Ende der Animation aufrufen müssen, können Sie die Änderungen in CATransaction wie folgt annehmen:

CATransaction.begin()
CATransaction.setCompletionBlock({() in self.tableview.reloadData() })
tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove.count ?? 0

// Do your work here
while numOfCellsToRemove > 0 {
     // ...or here, if you need to add/remove the same amount of objects to/from somewhere
     indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
     numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()
CATransaction.commit()

Die Logik wird für den Fall angezeigt, wenn Sie Zeilen löschen. Dieselbe Idee funktioniert jedoch auch beim Hinzufügen von Zeilen. Sie können die Animation auch in UITableViewRowAnimation.Left ändern, um sie übersichtlicher zu gestalten, oder aus der Liste der anderen verfügbaren Animationen auswählen.

1
Vitalii

Wenn Sie Ihre eigenen benutzerdefinierten Animationen zu UITableView-Zellen hinzufügen möchten, verwenden Sie 

[theTableView reloadData];
[theTableView layoutSubviews];
NSArray* visibleViews = [theTableView visibleCells];

um ein Array von sichtbaren Zellen zu erhalten. Fügen Sie dann jeder Zelle eine benutzerdefinierte Animation hinzu.

Schauen Sie sich diese Gist an, die ich für eine reibungslose benutzerdefinierte Zellanimation gepostet habe . https://Gist.github.com/floprr/1b7a58e4a18449d962bd

1
flopr

In meinem Fall wollte ich der Tabelle 10 weitere Zeilen hinzufügen (für die Funktion "Weitere Ergebnisse anzeigen") und Folgendes tun:

  NSInteger tempNumber = self.numberOfRows;
  self.numberOfRows += 10;
  NSMutableArray *arrayOfIndexPaths = [[NSMutableArray alloc] init];
  for (NSInteger i = tempNumber; i < self.numberOfRows; i++) {
    [arrayOfIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
  }
  [self.tableView beginUpdates];
  [self.tableView insertRowsAtIndexPaths:arrayOfIndexPaths withRowAnimation:UITableViewRowAnimationTop];
  [self.tableView endUpdates];

In den meisten Fällen würden Sie anstelle von "self.numberOfRows" normalerweise die Anzahl der Objekte für die Tableview verwenden. Um sicherzustellen, dass diese Lösung für Sie gut funktioniert, muss "arrayOfIndexPaths" ein genaues Array der Indexpfade der einzufügenden Zeilen sein. Wenn die Zeile für einen dieser Indexpfade vorhanden ist, stürzt der Code möglicherweise ab. Sie sollten daher die Methode "reloadRowsAtIndexPaths: withRowAnimation:" für diese Indexpfade verwenden, um einen Absturz zu vermeiden

1
Lucas Chwe

alle Abschnitte neu laden , nicht nur eine mit benutzerdefinierte Dauer .

Benutzer duration Parameter von UIView.animate zum Einstellen der benutzerdefinierten Dauer.

UIView.animate(withDuration: 0.4, animations: { [weak self] in
    guard let `self` = self else { return }
    let indexSet = IndexSet(integersIn: 0..<self.tableView.numberOfSections)
    self.tableView.reloadSections(indexSet, with: UITableView.RowAnimation.fade)
})
0
JPetric