Pouvez-vous animer un changement de hauteur sur un UITableViewCell lorsqu'il est sélectionné?

voix
361

J'utilise un UITableViewdans mon application iPhone, et j'ai une liste de personnes qui appartiennent à un groupe. Je voudrais en sorte que lorsque l'utilisateur clique sur une personne en particulier ( en sélectionnant ainsi la cellule), la cellule se développe en hauteur pour afficher plusieurs contrôles d'interface utilisateur pour modifier les propriétés de cette personne.

Est-ce possible?

Créé 20/01/2009 à 04:17
source utilisateur
Dans d'autres langues...                            


21 réponses

voix
833

J'ai trouvé une solution très simple à cela comme un effet secondaire à un que UITableViewje travaillais sur .....

Rangez la hauteur de la cellule dans une variable qui indique la hauteur d' origine normalement via tableView: heightForRowAtIndexPath:, lorsque vous souhaitez animer un changement de hauteur, il suffit de changer la valeur de la variable et appeler cette ...

[tableView beginUpdates];
[tableView endUpdates];

Vous trouverez qu'il ne fait pas un rechargement complet mais il est assez pour le UITableViewsavoir qu'il doit redessiner les cellules, en saisissant la nouvelle valeur de la hauteur de la cellule .... et devinez quoi? Animez le changement pour vous. Doux.

J'ai une explication plus détaillée et des échantillons complets de code sur mon blog ... Animer UITableView cellulaire Taille changement

Créé 14/01/2010 à 12:42
source utilisateur

voix
56

J'aime la réponse par Simon Lee. Je n'ai pas essayé en fait cette méthode mais il semble que cela changerait la taille de toutes les cellules dans la liste. J'espérais un changement de juste la cellule qui est exploité. Je l'ai fait un peu comme Simon, mais avec juste une petite différence. Cela va changer l'apparence d'une cellule lorsqu'elle est sélectionnée. Et il n'Animer. Juste une autre façon de le faire.

Créer un int pour contenir une valeur de l'indice cellulaire courant sélectionné:

int currentSelection;

Alors:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    int row = [indexPath row];
    selectedNumber = row;
    [tableView beginUpdates];
    [tableView endUpdates];
}

Alors:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    if ([indexPath row] == currentSelection) {
        return  80;
    }
    else return 40;


}

Je suis sûr que vous pouvez apporter des modifications similaires à tableView: cellForRowAtIndexPath: pour changer le type de cellule ou même charger un fichier pour la cellule xib.

Comme cela, le currentSelection commencera à 0. Vous auriez besoin de faire des ajustements si vous ne voulez pas la première cellule de la liste (à l'index 0) à regarder à sélectionné par défaut.

Créé 26/04/2011 à 00:25
source utilisateur

voix
19

Ajouter une propriété de garder une trace de la cellule sélectionnée

@property (nonatomic) int currentSelection;

Réglez - le à une valeur sentinelle (par exemple) viewDidLoad, pour vous assurer que les UITableViewdéparts en position « normale »

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    //sentinel
    self.currentSelection = -1;
}

En heightForRowAtIndexPathvous pouvez définir la hauteur souhaitée pour la cellule sélectionnée

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    int rowHeight;
    if ([indexPath row] == self.currentSelection) {
        rowHeight = self.newCellHeight;
    } else rowHeight = 57.0f;
    return rowHeight;
}

En didSelectRowAtIndexPathvous enregistrer la sélection en cours et enregistrer une hauteur dynamique, si nécessaire

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        // do things with your cell here

        // set selection
        self.currentSelection = indexPath.row;
        // save height for full text label
        self.newCellHeight = cell.titleLbl.frame.size.height + cell.descriptionLbl.frame.size.height + 10;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}

Dans didDeselectRowAtIndexPathrégler l'indice de sélection revenir à la valeur sentinelle et animer la cellule de retour à la forme normale

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {       
        // do things with your cell here

        // sentinel
        self.currentSelection = -1;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}
Créé 05/08/2013 à 17:02
source utilisateur

voix
12

reloadData est pas bon parce qu'il n'y a pas d'animation ...

Voilà ce que je suis en train d'essayer:

NSArray* paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];

Il fonctionne presque à droite. Presque. Je suis de plus en plus la hauteur de la cellule, et parfois il y a un peu « hoquet » dans la vue de la table que la cellule est remplacée, comme si une position de défilement dans la vue de la table est conservée, la nouvelle cellule (qui est la première cellule dans le tableau) se termine avec son décalage trop élevé, et le scrollview rebondit pour le repositionner.

Créé 07/05/2009 à 00:24
source utilisateur

voix
10

Je résolus avec reloadRowsAtIndexPaths.

Je sauve dans didSelectRowAtIndexPathla indexPath de cellule sélectionnée et appeler reloadRowsAtIndexPathsà la fin (vous pouvez envoyer NSMutableArray pour la liste de toi élément voulez reload).

En heightForRowAtIndexPathvous pouvez vérifier si indexPath est dans la liste ou non de cellules de expandIndexPath et envoyer la hauteur.

Vous pouvez vérifier cet exemple de base: https://github.com/ferminhg/iOS-Examples/tree/master/iOS-UITableView-Cell-Height-Change/celdascambiadetam Il est une solution simple.

ajouter une sorte de code si vous aider

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 20;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath
{
    if ([indexPath isEqual:_expandIndexPath])
        return 80;

    return 40;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Celda";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    [cell.textLabel setText:@"wopwop"];

    return cell;
}

#pragma mark -
#pragma mark Tableview Delegate Methods

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSMutableArray *modifiedRows = [NSMutableArray array];
    // Deselect cell
    [tableView deselectRowAtIndexPath:indexPath animated:TRUE];
    _expandIndexPath = indexPath;
    [modifiedRows addObject:indexPath];

    // This will animate updating the row sizes
    [tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];
}
Créé 14/11/2014 à 13:20
source utilisateur

voix
10

Je ne sais pas ce que tout ce genre de choses à appeler beginUpdates / endUpdates successivement est, vous pouvez simplement utiliser -[UITableView reloadRowsAtIndexPaths:withAnimation:]. Voici un exemple de projet .

Créé 02/08/2014 à 23:52
source utilisateur

voix
2
BOOL flag;

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    flag = !flag;
    [tableView beginUpdates];
    [tableView reloadRowsAtIndexPaths:@[indexPath] 
                     withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView endUpdates];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES == flag ? 20 : 40;
}
Créé 15/08/2016 à 16:32
source utilisateur

voix
2

juste une note pour quelqu'un comme moi la recherche d'ajouter « Plus de détails » sur la cellule de mesure.

[tableView beginUpdates];
[tableView endUpdates];

Est - ce un excellent travail, mais ne pas oublier de vue cellulaire « cultures ». De Interface Builder sélectionnez votre portable -> Contenu Affichage -> de la propriété Inspecteur sélectionnez « clip sous - vue »

Créé 25/03/2015 à 20:08
source utilisateur

voix
2

Essayez ceci est d'étendre la ligne indexwise:

@property (nonatomic) NSIndexPath *expandIndexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
if ([indexPath isEqual:self.expandedIndexPath])
    return 100;

return 44;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *modifiedRows = [NSMutableArray array];
if ([indexPath isEqual:self.expandIndexPath]) {
    [modifiedRows addObject:self.expandIndexPath];
    self.expandIndexPath = nil;
} else {
    if (self.expandedIndexPath)
        [modifiedRows addObject:self.expandIndexPath];

    self.expandIndexPath = indexPath;
    [modifiedRows addObject:indexPath];
}

// This will animate updating the row sizes
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];

// Preserve the deselection animation (if desired)
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ViewControllerCellReuseIdentifier];
    cell.textLabel.text = [NSString stringWithFormat:@"I'm cell %ld:%ld", (long)indexPath.section, (long)indexPath.row];

return cell;
}
Créé 24/09/2014 à 06:41
source utilisateur

voix
1

Au lieu de beginUpdates()/ endUpdates(), l'appel est recommandé maintenant:

tableView.performBatchUpdates(nil, completion: nil)

Apple dit, en ce qui concerne beginUpdates / endUpdates: "Les performBatchUpdates (_: achèvement :) méthode au lieu de celui-ci lorsque cela est possible."

Voir: https://developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates

Créé 19/11/2018 à 16:47
source utilisateur

voix
1

Heres une version plus courte de la réponse Simons Swift 3. permet également la sélection de basculement de la cellule

var cellIsSelected: IndexPath?


  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    cellIsSelected = cellIsSelected == indexPath ? nil : indexPath
    tableView.beginUpdates()
    tableView.endUpdates()
  }


  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if cellIsSelected == indexPath {
      return 250
    }
    return 65
  }
Créé 30/05/2017 à 23:36
source utilisateur

voix
1

Swift version de la réponse de Simon Lee.

// MARK: - Variables 
  var isCcBccSelected = false // To toggle Bcc.



    // MARK: UITableViewDelegate
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

    // Hide the Bcc Text Field , until CC gets focused in didSelectRowAtIndexPath()
    if self.cellTypes[indexPath.row] == CellType.Bcc {
        if (isCcBccSelected) {
            return 44
        } else {
            return 0
        }
    }

    return 44.0
}

Puis, en didSelectRowAtIndexPath ()

  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    self.tableView.deselectRowAtIndexPath(indexPath, animated: true)

    // To Get the Focus of CC, so that we can expand Bcc
    if self.cellTypes[indexPath.row] == CellType.Cc {

        if let cell = tableView.cellForRowAtIndexPath(indexPath) as? RecipientTableViewCell {

            if cell.tag == 1 {
                cell.recipientTypeLabel.text = "Cc:"
                cell.recipientTextField.userInteractionEnabled = true
                cell.recipientTextField.becomeFirstResponder()

                isCcBccSelected = true

                tableView.beginUpdates()
                tableView.endUpdates()
            }
        }
    }
}
Créé 07/06/2016 à 15:30
source utilisateur

voix
0

Swift 4 et au-dessus

ajouter ci-dessous le code dans vous didselect méthode déléguée de la ligne de tableview

tableView.beginUpdates()
tableView.setNeedsLayout()
tableView.endUpdates()
Créé 23/11/2018 à 11:53
source utilisateur

voix
0

Contributions -

tableView.beginUpdates () tableView.endUpdates () ces fonctions ne remettront pas

func tableView (_ tableView: UITableView, cellForRowAt indexPath: indexPath) -> UITableViewCell {}

Mais, si vous le faites, tableView.reloadRows (à: [selectedIndexPath comme indexPath!], Avec: .NONE)

Il appellera le fonc tableView (_ tableView: UITableView, cellForRowAt indexPath: indexPath) -> {} UITableViewCell cette fonction.

Créé 28/03/2018 à 11:08
source utilisateur

voix
0

Version rapide de la réponse de Simon Lee :

tableView.beginUpdates()
tableView.endUpdates()

Gardez à l' esprit que vous devez modifier les propriétés de hauteur AVANT endUpdates() .

Créé 08/02/2018 à 14:11
source utilisateur

voix
0

Oui c'est possible.

UITableView a une méthode déléguée didSelectRowAtIndexPath

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [UIView animateWithDuration:.6
                          delay:0
         usingSpringWithDamping:UIViewAnimationOptionBeginFromCurrentState
          initialSpringVelocity:0
                        options:UIViewAnimationOptionBeginFromCurrentState animations:^{

                            cellindex = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
                            NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
                            [violatedTableView beginUpdates];
                            [violatedTableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationAutomatic];
                            [violatedTableView endUpdates];
                        }
                     completion:^(BOOL finished) {
    }];
}

Mais dans votre cas si l'utilisateur fait défiler et sélectionne une autre cellule alors u besoin d'avoir la dernière cellule sélectionnée pour rétrécir et élargir la cellule actuellement sélectionnée reloadRowsAtIndexPaths:appels heightForRowAtIndexPath:gérer de manière en conséquence.

Créé 01/08/2016 à 11:29
source utilisateur

voix
0

Cochez cette méthode après iOS 7 et versions ultérieures.

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return UITableViewAutomaticDimension;
}

Des améliorations ont été apportées à ce dans iOS 8. Nous pouvons la définir comme propriété de la vue de la table elle-même.

Créé 04/03/2016 à 12:10
source utilisateur

voix
0

Je @ réponse impressionnant de joie, et cela a fonctionné parfaitement avec ios 8.4 et Xcode 7.1.1.

Si vous cherchez à faire de votre cellule bascule-mesure, j'ai changé le -tableViewDidSelect à ce qui suit:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//This is the bit I changed, so that if tapped once on the cell, 
//cell is expanded. If tapped again on the same cell, 
//cell is collapsed. 
    if (self.currentSelection==indexPath.row) {
        self.currentSelection = -1;
    }else{
        self.currentSelection = indexPath.row;
    }
        // animate
        [tableView beginUpdates];
        [tableView endUpdates];

}

J'espère que tout cela vous a aidé.

Créé 19/11/2015 à 21:00
source utilisateur

voix
0

Voici mon code de la coutume UITableViewsous - classe, qui se dilatent UITextViewà la cellule de table, sans rupture de charge (et perdu le focus du clavier):

- (void)textViewDidChange:(UITextView *)textView {
    CGFloat textHeight = [textView sizeThatFits:CGSizeMake(self.width, MAXFLOAT)].height;
    // Check, if text height changed
    if (self.previousTextHeight != textHeight && self.previousTextHeight > 0) {
        [self beginUpdates];

        // Calculate difference in height
        CGFloat difference = textHeight - self.previousTextHeight;

        // Update currently editing cell's height
        CGRect editingCellFrame = self.editingCell.frame;
        editingCellFrame.size.height += difference;
        self.editingCell.frame = editingCellFrame;

        // Update UITableView contentSize
        self.contentSize = CGSizeMake(self.contentSize.width, self.contentSize.height + difference);

        // Scroll to bottom if cell is at the end of the table
        if (self.editingNoteInEndOfTable) {
            self.contentOffset = CGPointMake(self.contentOffset.x, self.contentOffset.y + difference);
        } else {
            // Update all next to editing cells
            NSInteger editingCellIndex = [self.visibleCells indexOfObject:self.editingCell];
            for (NSInteger i = editingCellIndex; i < self.visibleCells.count; i++) {
                UITableViewCell *cell = self.visibleCells[i];
                CGRect cellFrame = cell.frame;
                cellFrame.origin.y += difference;
                cell.frame = cellFrame;
            }
        }
        [self endUpdates];
    }
    self.previousTextHeight = textHeight;
}
Créé 10/11/2015 à 02:14
source utilisateur

voix
-1

Je viens résolu ce problème avec un petit hack:

static int s_CellHeight = 30;
static int s_CellHeightEditing = 60;

- (void)onTimer {
    cellHeight++;
    [tableView reloadData];
    if (cellHeight < s_CellHeightEditing)
        heightAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(onTimer) userInfo:nil repeats:NO] retain];
}

- (CGFloat)tableView:(UITableView *)_tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
        if (isInEdit) {
            return cellHeight;
        }
        cellHeight = s_CellHeight;
        return s_CellHeight;
}

Quand je dois augmenter la hauteur de la cellule que je mets isInEdit = YESet appeler la méthode [self onTimer]et il anime la croissance cellulaire jusqu'à ce qu'elle atteigne la valeur s_CellHeightEditing :-)

Créé 20/08/2009 à 21:18
source utilisateur

voix
-1

Obtenez le indexPath de la ligne sélectionnée. Recharger la table. Dans le procédé de heightForRowAtIndexPath UITableViewDelegate, régler la hauteur de la ligne sélectionnée à une hauteur différente et pour les autres revenir la hauteur de ligne normale

Créé 21/01/2009 à 16:13
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more