Si può animare un cambiamento di altezza su un'UITableViewCell quando selezionato?

voti
361

Io sto usando un UITableViewnel mio iPhone app, e ho una lista di persone che appartengono a un gruppo. Desidero in modo che quando l'utente clicca su una particolare persona (selezionando così la cella), la cella si sviluppa in altezza per visualizzare diversi controlli dell'interfaccia utente per modificare le proprietà di tale persona.

È possibile?

È pubblicato 20/01/2009 alle 04:17
fonte dall'utente
In altre lingue...                            


21 risposte

voti
833

Ho trovato una soluzione molto semplice a questo come un effetto collaterale di uno UITableViewstavo lavorando su .....

Conservare l'altezza della cella in una variabile che riporta l'altezza originaria normalmente via la tableView: heightForRowAtIndexPath:, poi, quando si vuole animare un cambiamento di altezza, è sufficiente modificare il valore della variabile e chiamare questo ...

[tableView beginUpdates];
[tableView endUpdates];

Troverete che non fa una ricarica completa, ma è sufficiente per il UITableViewsapere deve ridisegnare le cellule, afferrando il nuovo valore di altezza per la cella .... e indovinate un po? Si anima il cambiamento per voi. Dolce.

Ho un più dettagliati esempi di spiegazione e di codice completo sul mio blog ... Animare UITableView Altezza cella Change

Risposto il 14/01/2010 a 12:42
fonte dall'utente

voti
56

Mi piace la risposta di Simon Lee. Non ho effettivamente provare questo metodo, ma sembra che sarebbe cambiare la dimensione di tutte le cellule nella lista. Speravo in un cambiamento del proprio cellulare che viene sfruttato. I kinda fatto come Simon, ma con solo una piccola differenza. Questo cambierà l'aspetto di una cella quando è selezionato. E lo fa animare. Solo un altro modo per farlo.

Creare un int per contenere un valore per l'indice cella selezionata corrente:

int currentSelection;

Poi:

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

Poi:

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

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


}

Sono sicuro che è possibile apportare modifiche simili a Tableview: cellForRowAtIndexPath: per cambiare il tipo di cellula o addirittura caricare un file XI ter per la cella.

In questo modo, il currentSelection inizierà a 0. Si avrebbe bisogno di apportare modifiche se non si desidera che la prima cella della lista (indice 0) per guardare selezionata per impostazione predefinita.

Risposto il 26/04/2011 a 00:25
fonte dall'utente

voti
19

Aggiungere una proprietà per tenere traccia della cella selezionata

@property (nonatomic) int currentSelection;

Impostare a un valore sentinella (per esempio) viewDidLoad, per assicurarsi che le UITableViewinizia nella posizione 'normale'

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

    //sentinel
    self.currentSelection = -1;
}

In heightForRowAtIndexPathè possibile impostare l'altezza desiderata per la cella selezionata

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

In didSelectRowAtIndexPathrisparmiare la selezione corrente e salvare un'altezza dinamica, se richiesto

- (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];
    }
}

In didDeselectRowAtIndexPathimpostare l'indice di selezione al valore sentinella e animare la cella torna alla forma normale

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

        // sentinel
        self.currentSelection = -1;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}
Risposto il 05/08/2013 a 17:02
fonte dall'utente

voti
12

reloadData è non va bene perché non c'è animazione ...

Questo è quello che sto attualmente cercando:

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];

Funziona quasi giusto. Quasi. Sto aumentando l'altezza della cella, e, a volte c'è un po ' "incidente di percorso" nella vista tabella come la cellula è sostituito, come se una posizione di scorrimento nella vista tabella viene conservato, la nuova cella (che è la prima cella nella tabella) finisce con il suo offset troppo elevata, e ScrollView rimbalzare per riposizionarla.

Risposto il 07/05/2009 a 00:24
fonte dall'utente

voti
10

Ho risolto con reloadRowsAtIndexPaths.

Risparmio didSelectRowAtIndexPathnella l'indexPath della cella selezionata e chiamare reloadRowsAtIndexPathsalla fine (è possibile inviare NSMutableArray per la lista degli elementi che si desidera di ricarica).

In heightForRowAtIndexPathè possibile controllare se indexPath è nella lista o non di cella di expandIndexPath e inviare altezza.

È possibile controllare questo esempio di base: https://github.com/ferminhg/iOS-Examples/tree/master/iOS-UITableView-Cell-Height-Change/celdascambiadetam Si tratta di una soluzione semplice.

aggiungo una sorta di codice se aiutare

- (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];
}
Risposto il 14/11/2014 a 13:20
fonte dall'utente

voti
10

Non so che cosa tutta questa roba di chiamare beginUpdates / endUpdates in successione è, si può semplicemente utilizzare -[UITableView reloadRowsAtIndexPaths:withAnimation:]. Ecco un esempio di progetto .

Risposto il 02/08/2014 a 23:52
fonte dall'utente

voti
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;
}
Risposto il 15/08/2016 a 16:32
fonte dall'utente

voti
2

Solo una nota per uno come me alla ricerca di aggiungere "Maggiori dettagli" a cella personalizzato.

[tableView beginUpdates];
[tableView endUpdates];

Ha fatto un ottimo lavoro, ma non dimenticate di vista di cella "raccolto". Da Interface Builder selezionare il tuo cellulare -> contenuti -> dalla finestra di ispezione Proprietà selezionare " visualizzazione secondaria clip "

Risposto il 25/03/2015 a 20:08
fonte dall'utente

voti
2

Prova questo è per espansione fila 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;
}
Risposto il 24/09/2014 a 06:41
fonte dall'utente

voti
1

Invece di beginUpdates()/ endUpdates(), la chiamata consigliata è ora:

tableView.performBatchUpdates(nil, completion: nil)

Apple dice, per quanto riguarda beginUpdates / endUpdates: "Utilizzare i performBatchUpdates (_:. Completamento metodo invece di questo, quando possibile :)"

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

Risposto il 19/11/2018 a 16:47
fonte dall'utente

voti
1

Heres una versione più breve di Simons risposta per Swift 3. consente inoltre di commutazione della selezione della cellula

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
  }
Risposto il 30/05/2017 a 23:36
fonte dall'utente

voti
1

Swift versione della risposta di 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
}

Poi, nel 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()
            }
        }
    }
}
Risposto il 07/06/2016 a 15:30
fonte dall'utente

voti
0

Swift 4 e superiori

aggiungi sottostante Codice in voi metodo fila delegato didselect di Tableview

tableView.beginUpdates()
tableView.setNeedsLayout()
tableView.endUpdates()
Risposto il 23/11/2018 a 11:53
fonte dall'utente

voti
0

ingressi -

tableView.beginUpdates () tableView.endUpdates () queste funzioni non chiamerà

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

Ma, se lo fai, tableView.reloadRows (a: [selectedIndexPath come IndexPath!], Con: .none)

Si chiamerà la tableView func (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {} questa funzione.

Risposto il 28/03/2018 a 11:08
fonte dall'utente

voti
0

Versione Swift di risposta di Simon Lee :

tableView.beginUpdates()
tableView.endUpdates()

Tenete a mente che è necessario modificare le proprietà di altezza PRIMA endUpdates() .

Risposto il 08/02/2018 a 14:11
fonte dall'utente

voti
0

Si è possibile.

UITableView ha un metodo delegato 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) {
    }];
}

Ma nel tuo caso, se l'utente scorre e seleziona una cella diversa allora u bisogno di avere l'ultima cella selezionata a ridursi ed espandere la cella selezionata reloadRowsAtIndexPaths:chiamate heightForRowAtIndexPath:in modo di gestire di conseguenza.

Risposto il 01/08/2016 a 11:29
fonte dall'utente

voti
0

Controllare questo metodo dopo iOS 7 e versioni successive.

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

Miglioramenti sono stati fatti per questo IOS 8. Possiamo impostarla come proprietà della visualizzazione tabella stessa.

Risposto il 04/03/2016 a 12:10
fonte dall'utente

voti
0

Ho usato @ risposta impressionante di Joy, e ha funzionato perfettamente con iOS 8.4 e XCode 7.1.1.

Nel caso in cui si sta cercando di rendere il vostro cellulare a ginocchiera in grado, ho cambiato il -tableViewDidSelect al seguente:

-(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];

}

Spero che tutto questo si aiutato.

Risposto il 19/11/2015 a 21:00
fonte dall'utente

voti
0

Ecco il mio codice di personalizzato UITableViewsottoclasse, che si espandono UITextViewa cella di una tabella, senza ricaricare (e messa a fuoco della tastiera perso):

- (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;
}
Risposto il 10/11/2015 a 02:14
fonte dall'utente

voti
-1

Ho appena risolto questo problema con un piccolo 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;
}

Quando ho bisogno di espandere l'altezza della cella a impostare isInEdit = YESe chiamare il metodo [self onTimer]e anima la crescita cellulare fino a raggiungere il valore s_CellHeightEditing :-)

Risposto il 20/08/2009 a 21:18
fonte dall'utente

voti
-1

Prendi l'indexpath della riga selezionata. Ricaricare la tabella. Nel metodo di heightForRowAtIndexPath UITableViewDelegate, impostare l'altezza della riga selezionata ad una diversa altezza e per gli altri tornare alla normale altezza di righe

Risposto il 21/01/2009 a 16:13
fonte dall'utente

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