Expansion des cellules de vue de table disparaissant

J'ai des cellules qui se développent en changeant leur taille avec un setExpanded: appel de méthode.

J'appelle ensuite reloadRowsAtIndexPaths: pour actualiser les cellules.

Le problème est que les cellules disparaissent simplement et réapparaissent au hasard. Je suppose que cela doit être dû à la façon dont l'indexing fonctionne.

Si j'appelle reloadData ou beginUpdates / endUpdates, les cellules fonctionnent comme prévu, mais je perds les animations.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { JVCell *cell = (JVCell*)[tableView cellForRowAtIndexPath:indexPath]; JVCell *previousCell = nil; if( previousIndexPath_ != nil ) // set to nil in viewDidLoad { previousCell = (JVCell*)[tableView cellForRowAtIndexPath:previousIndexPath_]; } // expand or collapse cell if it's the same one as last time if( previousCell != nil && [previousIndexPath_ compare:indexPath] == NSOrderedSame && [previousCell expandable] ) { [previousCell setExpanded:![cell expanded]]; NSArray *indexPathArray = [NSArray arrayWithObject:previousIndexPath_]; [tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic]; } else { // collapse previous cell if( previousCell != nil && [previousCell expandable] ) { if( [previousCell expanded] ) [previousCell setExpanded:NO]; NSArray *indexPathArray = [NSArray arrayWithObject:previousIndexPath_]; [tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic]; } // expand new cell if( [cell expandable] ) { [cell setExpanded:YES]; NSArray *indexPathArray = [NSArray arrayWithObject:indexPath]; [tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic]; } } previousIndexPath_ = indexPath; // works as expected, but I lose the animations //[tableView reloadData]; // works as expected, but I lose the animations //[tableView beginUpdates]; //[tableView endUpdates]; } 

EDIT: mis à jour pour inclure les methods cellForRowAtIndexPath et heightForRowAtIndexPath:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger section = [indexPath section]; NSUInteger row = [indexPath row]; JVCellSectionData *sectionData = [sections_ objectAtIndex:section]; // NSArray of SectionData objects NSArray *cellArray = [sectionData cells]; // NSArray of cells UITableViewCell *cell = [cellArray objectAtIndex:row]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger section = [indexPath section]; NSUInteger row = [indexPath row]; JVCellSectionData *sectionData = [sections_ objectAtIndex:section]; NSArray *cellArray = [sectionData cells]; JVCell *cell = [cellArray objectAtIndex:row]; return [cell cellHeight]; // changed when selected with setExpanded: method } 

Edit 2: J'ai fait une video Quicktime de ce qui se passait et extrait des captures d'écran.

Ce que je tente de faire est d'élargir une cellule, pas replace, insert ou supprimer des cellules. Chaque cellule a une ou plusieurs sous-vues. La hauteur de la cellule change selon qu'elle est «étendue» ou non. La vue de contenu a les sous-vues ajoutées, et sa propriété clipToBounds est OUI. Lorsque les cellules se dilatent ou se rétractent, la valeur de hauteur change avec le cadre de la cellule (y compris la vue d'arrière-plan et la vue d'arrière-plan sélectionnée). J'ai enregistré toutes les valeurs d'images avant, pendant et après l'expansion, et elles sont toutes cohérentes avec leur état et leur position.

conception de vue de table sectionnée

cellule tapée

expansion cellulaire

cellule a disparu

la cellule se rétracte

cellule visible à nouveau

Gardez à l'esprit que cela fonctionne normalement sur iOS 4.3, comme indiqué ci-dessous:

comaprison ios 4 à ios 5

Je ne vois aucune différence de comportement entre iOS 5.0 et 4.3.2 dans le simulateur, ou 5.0 sur mon téléphone, les cellules disparaissent de la même manière sur chacun. (Je testerais sur 4.2.1 sur mon iPod touch plus ancien mais Xcode 4 ne peut pas .. Grr ..) Il semble qu'il y ait une solution de contournement facile, cependant: Si vous faites les deux reloadRowsAtIndexPaths: withRowAnimation: après expansion / effondrement de vos cellules et puis l'appel reloadData après cela, il semble conserver l'animation.

Voici un petit projet de démonstration pour ça. Il est difficile de dire quel était le problème réel – c'est juste un étrange effet secondaire de la façon dont UIKit fait l'animation de la cellule. Si vous sous-classz [UITableViewCell setAlpha:], vous pouvez voir que la vue de table définit l'alpha de la cellule à 0 et le laisse là. Bizarre.

Edit: Eh bien c'est bizarre. Ça ne fonctionnait pas un peu (faisait l'ancien comportement, avec des cellules qui disparaissaient), mais maintenant c'est bon. Peut-être que je courais la mauvaise version. Quoi qu'il en soit, laissez-moi savoir si cela fonctionne pour vous.

J'ai eu le même problème. Je confirme que l'utilisation d'aucune animation lors du rechargement de la ligne fonctionne bien.

Mais il s'avère que le problème est dû au return d'un UITableViewCell mis en cache dans cellForRowAtIndexPath alors qu'un nouveau file est nécessaire.

Le document pour reloadRowsAtIndexPaths: withRowAnimation: dit: "Le rechargement d'une ligne provoque l'affichage par la table de sa source de données pour une nouvelle cellule pour cette ligne."

Votre méthode cellForRowAtIndexPath renvoie des cellules mises en cache localement. Le return d'une nouvelle cellule a résolu le problème dans mon cas et aucune solution de rechange n'était nécessaire …

@Javy,

Merci pour votre question Je développais une table avec un comportement similaire: il y a des vues de text ( UITextView ) dans mes cellules de vue de table ( UITableViewCell ) qui sont:

  1. expansion si une nouvelle ligne est nécessaire pour afficher le text sans défilement, ou
  2. effondrement si une nouvelle ligne a été supprimée

J'ai donc trouvé le même problème. Dans iOS 5.x quand je commençais à taper du text, il devenait soudainement invisible. Mais dans iOS 4.x tout fonctionne bien.

J'ai trouvé la solution et ça marche bien pour moi.

Solution: Essayez simplement de replace votre type d'animation UITableViewRowAnimationAutomatic par UITableViewRowAnimationNone lors du rechargement de la cellule en question.

Du code supplémentaire: recharger les deux cellules en un instant:

  NSMutableArray *indexes = [NSMutableArray arrayWithCapacity:2]; // collapse previous cell if( previousCell != nil && [previousCell expandable] ) { if( [previousCell expanded] ) [previousCell setExpanded:NO]; [indexes addObject:previousIndexPath_]; } // expand new cell if( [cell expandable] ) { [cell setExpanded:YES]; [indexes addObject:indexPath]; } [tableView reloadRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationNone]; 

J'espère que cela vous aidera.

Il me semble que la cellule n'est pas redessinée correctement.

Avez-vous essayé quelque chose comme:

 [cell.backgroundView setNeedsDisplay] 

vous pourriez essayer de recharger la vue de table quand les animations ont accompli? pour le moment, si vos animations sont [tableView reloadData] , et que vous appelez [tableView reloadData] les animations ne seront pas terminées, ainsi le cadre, etc., pourrait ne plus être synchronisé

vous pouvez changer votre méthode étendue de jeu pour prendre un drapeau ainsi qu'un bloc d'achèvement d'animation, qui pourrait contenir le code de rechargement

 [cell setExpanded:YES completion:^ //reload code }]; 

Dans:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

vous devez renvoyer une nouvelle cellule. Si vous n'avez pas besoin de créer une nouvelle cellule, vous avez seulement besoin de:

 [tableView beginUpdates]; [tableView endUpdates]; 

Il n'est pas nécessaire d'appeler reloadRowsAtIndexPaths .

D'accord…

Avant toi

 previousIndexPath_ = indexPath; 

et après que vous fassiez tout l'expansion / contrat des hauteurs etc. vous devez faire quelque chose comme

 [cellArray replaceObjectAtIndex:previousIndexPath_ withObject:previousCell]; [cellArray replaceObjectAtIndex:indexPath withObject:cell]; 

ce qui signifie que votre cellArray doit être

 NSMutableArray* cellArray;