J'ai un UITableView
, où il y a un UISegmentedControl
dans la vue en-tête. Cela devrait fonctionner exactement comme dans l'application App Store: lorsque l'utilisateur fait défiler, le titre de l'en-tête disparaît de l'écran, mais la variable segmentedControl
reste collée sous la variable navigationBar
.
Lorsque l'utilisateur sélectionne un segment, la section située sous l'en-tête doit être rechargée avec une variable Nice UITableViewRowAnimation
. Cependant, lorsque j'appelle tableView:reloadSections:withRowAnimation:
, la vue d'en-tête est également animée, ce que je veux empêcher, car elle a l'air terrible.
Voici mon code pour ceci:
- (void)selectedSegmentIndexChanged:(UISegmentedControl *)sender
{
int index = sender.selectedSegmentIndex;
if (index < self.oldIndex) {
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationLeft];
} else if (index > self.oldIndex) {
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationRight];
}
self.oldIndex = index;
}
Quelqu'un a une idée de comment recharger la section sous l'en-tête sans recharger l'en-tête lui-même?
Peut-être devriez-vous essayer avec
[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationLeft] //or UITableViewRowAnimationRight
Cependant, je ne suis pas sûr mais je pense que cela peut générer une erreur dans le cas où vous avez moins de lignes à recharger que précédemment.
Je pense que vous pourriez traiter avec [tableView beginUpdates]
et [tableView endUpdates]
pour résoudre votre problème.
Par exemple, vous avez 2 tableaux de données à afficher. Laissez-les nommer oldArray
et newArray
. Un exemple de ce que vous pourriez faire:
- (void)selectedSegmentIndexChanged:(UISegmentedControl *)sender
{
[self.tableView setDataSource: newArray];
int nbRowToDelete = [oldArray count];
int nbRowToInsert = [newArray count];
NSMutableArray *indexPathsToInsert = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < nbRowToInsert; i++) {
[indexPathsToInsert addObject:[NSIndexPath indexPathForRow:i inSection:section]];
}
NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < nbRowToDelete; i++) {
[indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:section]];
}
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:UITableViewRowAnimationRight];
[self.tableView endUpdates];
}
Si vous utilisez Swift 2.0 , n'hésitez pas à utiliser cette extension.
Soyez averti (e) : si vous programmez la mauvaise variable oldCount
ou newCount
.
extension UITableView{
func reloadRowsInSection(section: Int, oldCount:Int, newCount: Int){
let maxCount = max(oldCount, newCount)
let minCount = min(oldCount, newCount)
var changed = [NSIndexPath]()
for i in minCount..<maxCount {
let indexPath = NSIndexPath(forRow: i, inSection: section)
changed.append(indexPath)
}
var reload = [NSIndexPath]()
for i in 0..<minCount{
let indexPath = NSIndexPath(forRow: i, inSection: section)
reload.append(indexPath)
}
beginUpdates()
if(newCount > oldCount){
insertRowsAtIndexPaths(changed, withRowAnimation: .Fade)
}else if(oldCount > newCount){
deleteRowsAtIndexPaths(changed, withRowAnimation: .Fade)
}
if(newCount > oldCount || newCount == oldCount){
reloadRowsAtIndexPaths(reload, withRowAnimation: .None)
}
endUpdates()
}
Essaye ça:
BOOL needsReloadHeader = YES;
UIView *oldHeaderView = nil;
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headerToReturn = nil;
if(needsReloadHeader == YES) {
headerToReturn = [[UIView alloc] init];
// ...
// custom your header view in this block
// and save
// ...
oldHeaderView = headerToReturn;
} else {
headerToReturn = oldHeaderView;
}
return headerToReturn;
}
Il vous suffit de changer "needsReloadHeader" en "NO" ailleurs.
Une version objective-c de l'extension Intentss
@interface UITableView (Extensions)
- (void)reloadRowsInSection:(NSUInteger)sectionIndex withRowAnimation:(UITableViewRowAnimation)rowAnimation oldCount:(NSUInteger)oldCount newCount:(NSUInteger)newCount;
@end
@implementation UITableView (Extensions)
- (void)reloadRowsInSection:(NSUInteger)sectionIndex withRowAnimation:(UITableViewRowAnimation)rowAnimation oldCount:(NSUInteger)oldCount newCount:(NSUInteger)newCount {
NSUInteger minCount = MIN(oldCount, newCount);
NSMutableArray *insert = [NSMutableArray array];
NSMutableArray *delete = [NSMutableArray array];
NSMutableArray *reload = [NSMutableArray array];
for (NSUInteger row = oldCount; row < newCount; row++) {
[insert addObject:[NSIndexPath indexPathForRow:row inSection:sectionIndex]];
}
for (NSUInteger row = newCount; row < oldCount; row++) {
[delete addObject:[NSIndexPath indexPathForRow:row inSection:sectionIndex]];
}
for (NSUInteger row = 0; row < minCount; row++) {
[reload addObject:[NSIndexPath indexPathForRow:row inSection:sectionIndex]];
}
[self beginUpdates];
[self insertRowsAtIndexPaths:insert withRowAnimation:rowAnimation];
[self deleteRowsAtIndexPaths:delete withRowAnimation:rowAnimation];
[self reloadRowsAtIndexPaths:reload withRowAnimation:rowAnimation];
[self endUpdates];
}
@end
Voici une autre manière d’utiliser et d’utiliser des animations.
Supposons que vous ayez une source de données dynamique, qui change lorsque vous sélectionnez quelque chose, et que vous souhaitez mettre à jour uniquement les lignes de cette section, sans toucher à l'en-tête de la section.
/** I get the desired handler from the handler collection. This handler is just a
simple NSObject subclass subscribed to UITableViewDelegate and UITableViewDataSource
protocols. **/
id handler = [self.tableViewHandlers objectForKey:[NSNumber numberWithInteger:index]];
/** Get the rows which will be deleted */
NSInteger numberOfRows = [self.tableView numberOfRowsInSection:sectionIndex];
NSMutableArray* indexPathArray = [NSMutableArray array];
for (int rowIndex = 0; rowIndex < numberOfRows; rowIndex++){
[indexPathArray addObject:[NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex]];
}
/** Update the handler */
[self.tableView setDataSource:handler];
[self.tableView setDelegate:handler];
/** Get the rows which will be added */
NSInteger newNumberOfRows = [handler tableView:self.tableView numberOfRowsInSection:sectionIndex];
NSMutableArray* newIndexPathArray = [NSMutableArray array];
for (int rowIndex = 0; rowIndex < newNumberOfRows; rowIndex++){
[newIndexPathArray addObject:[NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex]];
}
/** Perform updates */
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:newIndexPathArray withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
Remarque: veuillez vous en tenir à l'ordre des opérations spécifié, UITableView l'exige . Si vous n'avez qu'un seul gestionnaire (source de données et délégué), il est facile de modifier le code ci-dessus pour obtenir les mêmes résultats.
La réponse est simple: ne rechargez pas les sections animées, utilisez simplement UITableViewRowAnimationNone.
À l’heure actuelle, vous utilisez UITableViewRowAnimationLeft et UITableViewRowAnimationRight, qui permettent également d’insérer votre section.
Cependant, même avec UITableViewRowAnimationNone, les lignes seront toujours animées si le nombre de cellules avant la mise à jour diffère de celles après la mise à jour.
En outre, une bonne lecture sur ce sujet, ici .
À votre santé.
Vous rechargez la section, il est donc clair que tout dans la section sera rechargé (y compris l'en-tête).
Pourquoi ne pas placer plutôt UISegmentedControl dans la variable tableHeaderView
de UITableView? Cela permettrait exactement le comportement que vous recherchez.