Pouvez-vous faire des animations personnalisées pour les insertions de cellules UITableView?
J'ai un UITableView qui est rempli par un NSFetchedResultsController.
Sur la charge initiale de la table, je voudrais que la cellule d'animation, mais j'aimerais faire un peu plus d'animation personnalisée de
[tableView insertRowsAtIndexPaths:withRowAnimation:];
Permet. Plus précisément, je voudrais ralentir les animations et les avoir voler à côté d'une manière spécifique. Je n'ai pas été en mesure d'y parvenir par les constantes UITableViewRowAnimation. Existe-t-il un moyen d'utiliser L'Animation de base pour faire exactement ce que je veux ou dois-je m'en tenir aux animations UIKit dans ce cas spécifique?
Merci pour toute aide!
Joel
4 réponses
NOUVELLE SOLUTION (2017-12-12)
Ajout d'une version Swift 4.0 de la méthode animate. Il devrait alors être mis en œuvre de la même manière que la solution ci-dessous:
func animate() {
for cell in self.tableView.visibleCells {
cell.frame = CGRect(x: self.tableView.frame.size.width, y: cell.frame.origin.y, width: cell.frame.size.width, height: cell.frame.size.height)
UIView.animate(withDuration: 1.0) {
cell.frame = CGRect(x: 0, y: cell.frame.origin.y, width: cell.frame.size.width, height: cell.frame.size.height)
}
}
}
SOLUTION PLUS RÉCENTE(2015-09-05)
Ajout D'une version Swift 2.0 de la méthode animate. Il devrait alors être mis en œuvre de la même manière que la solution ci-dessous:
func animate() {
for cell in self.tableView.visibleCells {
cell.frame = CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)
UIView.animateWithDuration(1.0) {
cell.frame = CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)
}
}
}
NOUVELLE SOLUTION (2014-09-28)
J'ai retravaillé un peu la solution pour rendre l'implémentation plus plus facile et pour le faire fonctionner avec iOS8. Tout ce que vous devez faire est d'ajouter cette méthode animate
dans votre TableViewController et de l'appeler quand vous voulez qu'elle s'anime (par exemple, dans votre méthode reload, mais vous pouvez l'appeler à tout moment):
- (void)animate
{
[[self.tableView visibleCells] enumerateObjectsUsingBlock:^(UITableViewCell *cell, NSUInteger idx, BOOL *stop) {
[cell setFrame:CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
[UIView animateWithDuration:1 animations:^{
[cell setFrame:CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
}];
}];
}
Encore une fois, changez l'animation comme vous le souhaitez. Ce code particulier animera les cellules à partir de la droite à un rythme lent.
ANCIENNE SOLUTION (2013-06-06)
Vous pouvez le faire en implémentant votre propre UITableView et en remplaçant le méthode insertRowsAtIndexPaths. Voici un exemple de la façon dont cela pourrait ressembler à l'endroit où les cellules seront poussées de la droite, très lentement (1 seconde d'animation):
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
{
for (NSIndexPath *indexPath in indexPaths)
{
UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath];
[cell setFrame:CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
[UIView beginAnimations:NULL context:nil];
[UIView setAnimationDuration:1];
[cell setFrame:CGRectMake(0, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
[UIView commitAnimations];
}
}
, Vous pouvez jouer avec les animations vous-même. Cette méthode ne sera pas appelée automatiquement par la vue de table, vous devez donc remplacer la méthode reloadData dans votre délégué de vue de table et appeler cette méthode vous-même.
COMMENTAIRE
La méthode reloadData devrait ressembler à quelque chose comme ce:
- (void)reloadData
{
[super reloadData];
NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
for (int i = 0; i < [_data count]; i++)
[indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
[self insertRowsAtIndexPaths:indexPaths withRowAnimation:0];
}
La réponse de Materik n'a pas fonctionné pour moi avec le SDK iOS 7.1, j'ai nil après avoir appelé [self cellForRowAtIndexPath:indexPath];
Voici mon code dans la sous-classe de UITableView
:
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths
withRowAnimation:(UITableViewRowAnimation)animation
{
[super insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
[self endUpdates]; // Populates UITableView with data
[self beginUpdates];
for (NSIndexPath *indexPath in indexPaths) {
__block UITableViewCell *cell = [super cellForRowAtIndexPath:indexPath];
if (cell) { // If indexPath isn't visible we'll get nil here
// Custom animation
CGRect frame = cell.frame;
frame.origin.x = cell.frame.size.width;
cell.frame = frame;
frame.origin.x = 0;
void (^animationsBlock)() = ^{
cell.frame = frame;
};
if ([[UIView class] respondsToSelector:
@selector(animateWithDuration:delay:usingSpringWithDamping:
initialSpringVelocity:options:animations:completion:)]) {
[UIView animateWithDuration:0.3
delay:0
usingSpringWithDamping:0.5
initialSpringVelocity:0
options:0
animations:animationsBlock
completion:NULL];
} else {
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveEaseIn
animations:animationsBlock
completion:NULL];
}
}
}
}
Utilisez ceci:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
[cell setFrame:CGRectMake(320, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
[UIView animateWithDuration:2 animations:^{
[cell setFrame:CGRectMake(100, cell.frame.origin.y, cell.frame.size.width, cell.frame.size.height)];
}];
}
Swift 3.0 version de la réponse de Mattias Eriksson
func animate() {
for cell in tblView.visibleCells {
cell.frame = CGRect(x:320, y:cell.frame.origin.y, width:cell.frame.size.width, height:cell.frame.size.height)
UIView.animate(withDuration: 1.0) {
cell.frame = CGRect(x:0, y:cell.frame.origin.y, width:cell.frame.size.width, height:cell.frame.size.height)
}
}
}