J'ai un UITableView qui a deux modes. Lorsque nous basculons entre les modes, j'ai un nombre différent de sections et de cellules par section. Idéalement, il ferait une bonne animation lorsque la table s'agrandit ou diminue.
Voici le code que j'ai essayé, mais ça ne fait rien:
CGContextRef context = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.5];
[self.tableView reloadData];
[UIView commitAnimations];
Des idées sur comment je pourrais faire ça?
En fait, c'est très simple:
[_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
De la documentation :
L'appel de cette méthode entraîne l'affichage par la vue tabulaire de sa source de données nouvelles cellules pour les sections spécifiées. La vue tableau anime le fichier insertion de nouvelles cellules dans l'animation des anciennes cellules.
Vous voudrez peut-être utiliser:
Objectif c
[UIView transitionWithView: self.tableView
duration: 0.35f
options: UIViewAnimationOptionTransitionCrossDissolve
animations: ^(void)
{
[self.tableView reloadData];
}
completion: nil];
Rapide
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
Pas de soucis. :RÉ
Vous pouvez également utiliser l'une des variables UIViewAnimationOptionTransitions
que vous souhaitez pour des effets plus froids:
TransitionNone
TransitionFlipFromLeft
TransitionFlipFromRight
TransitionCurlUp
TransitionCurlDown
TransitionCrossDissolve
TransitionFlipFromTop
TransitionFlipFromBottom
CATransition
.(n'oubliez pas d'importer QuartzCore
)} _
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"];
Modifiez la type
pour qu'elle corresponde à vos besoins, par exemple kCATransitionFade
etc.
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()
Référence pour CATransition
Je crois que vous pouvez simplement mettre à jour votre structure de données, puis:
[tableView beginUpdates];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView endUpdates];
En outre, "withRowAnimation" n'est pas exactement un booléen, mais un style d'animation:
UITableViewRowAnimationFade,
UITableViewRowAnimationRight,
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone,
UITableViewRowAnimationMiddle
Toutes ces réponses supposent que vous utilisez un UITableView avec une seule section.
Pour gérer avec précision les situations dans lesquelles vous avez plusieurs sections, utilisez:
NSRange range = NSMakeRange(0, myTableView.numberOfSections);
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range];
[myTableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
(Remarque: vous devez vous assurer que vous avez plus de 0 sections!)
Une autre chose à noter est que vous pouvez rencontrer une exception NSInternalInconsistencyException si vous essayez de mettre à jour simultanément votre source de données avec ce code. Si tel est le cas, vous pouvez utiliser une logique similaire à celle-ci:
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];
La solution consiste à indiquer à la tableView de supprimer et d’ajouter des lignes et des sections avec le
insertRowsAtIndexPaths:withRowAnimation:
, deleteRowsAtIndexPaths:withRowAnimation:
, insertSections:withRowAnimation:
et deleteSections:withRowAnimation:
méthodes de UITableView. Lorsque vous appelez ces méthodes, la table animera les éléments que vous avez demandés, puis appelera reloadData sur elle-même afin que vous puissiez mettre à jour l'état après cette animation. Cette partie est importante: si vous animez tout en évitant de modifier les données renvoyées par la source de données de la table, les lignes réapparaîtront à la fin de l'animation.
Votre flux d’application serait donc:
[self setTableIsInSecondState:YES];
[myTable deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]];
Tant que les méthodes dataSource de votre table renvoient le nouvel ensemble correct de sections et de lignes en cochant [self tableIsInSecondState]
(ou autre), vous obtiendrez l'effet que vous recherchez.
Je ne peux pas commenter la réponse principale, mais une implémentation de Swift serait:
self.tableView.reloadSections([0], with: UITableViewRowAnimation.fade)
vous pouvez inclure autant de sections que vous souhaitez mettre à jour dans le premier argument de reloadSections.
Autres animations disponibles dans les documents: https://developer.Apple.com/reference/uikit/uitableviewrowanimation
fade La ou les lignes insérées ou supprimées apparaissent ou disparaissent en fondu dans la vue tabulaire.
right La ou les lignes insérées entrent par la droite; la ou les lignes supprimées glissent vers la droite.
left La ou les lignes insérées entrent par la gauche; la ou les lignes supprimées glissent vers la gauche.
top La ou les lignes insérées entrent par le haut; la ou les lignes supprimées glissent vers le haut.
bottom La ou les lignes insérées entrent par le bas; la ou les lignes supprimées glissent vers le bas.
case none Les lignes insérées ou supprimées utilisent les animations par défaut.
middle La vue de tableau tente de garder les anciennes et les nouvelles cellules centrées dans l'espace qu'elles occupaient ou occuperont. Disponible dans l'iPhone 3.2.
automatic La vue en tableau choisit un style d'animation approprié pour vous. (Introduit dans iOS 5.0.)
Mise en œuvre rapide:
let range = NSMakeRange(0, self.tableView!.numberOfSections())
let indexSet = NSIndexSet(indexesInRange: range)
self.tableView!.reloadSections(indexSet, withRowAnimation: UITableViewRowAnimation.Automatic)
Swift 4 version pour la réponse @dmarnel:
tableView.reloadSections(IndexSet(integer: 0), with: .automatic)
Pour Swift 4
tableView.reloadSections([0], with: UITableView.RowAnimation.fade)
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];
L'animation sans reloadData () dans Swift peut être faite comme ceci (à partir de la 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()
au cas où vous auriez besoin d'appeler reloadData () à la fin de l'animation, vous pouvez accepter les modifications apportées à CATransaction comme suit:
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()
La logique est indiquée pour le cas lorsque vous supprimez des lignes, mais la même idée fonctionne également pour l'ajout de lignes. Vous pouvez également modifier l'animation en UITableViewRowAnimation.Left pour la rendre ordonnée ou choisir dans la liste des autres animations disponibles.
Si vous souhaitez ajouter vos propres animations personnalisées aux cellules UITableView, utilisez
[theTableView reloadData];
[theTableView layoutSubviews];
NSArray* visibleViews = [theTableView visibleCells];
pour obtenir un tableau de cellules visibles. Ajoutez ensuite une animation personnalisée à chaque cellule.
Découvrez ce Gist que j'ai posté pour une animation de cellule personnalisée fluide . https://Gist.github.com/floprr/1b7a58e4a18449d962bd
Dans mon cas, je voulais ajouter 10 lignes supplémentaires dans la table (pour un type de fonctionnalité "afficher plus de résultats") et j'ai procédé comme suit:
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];
Dans la plupart des cas, au lieu de "self.numberOfRows", vous utiliseriez généralement le nombre d'objets du tableau pour la vue de table. Pour que cette solution fonctionne bien pour vous, "arrayOfIndexPaths" doit donc être un tableau précis des chemins d'index des lignes insérées. Si la ligne existe pour l'un de ces chemins d'index, le code peut se bloquer, vous devez donc utiliser la méthode "reloadRowsAtIndexPaths: withRowAnimation:" pour ces chemins d'index afin d'éviter leur blocage
Pour recharger toutes les sections , pas une seule avec durée personnalisée .
User duration
paramètre de UIView.animate
pour définir la durée personnalisée.
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)
})