2014-11-24 14 views
6

Sto provando a ricaricare un singolo TableViewCell ma scorre verso l'alto ogni volta che lo faccio ... Non sto aggiungendo né cancellando celle, voglio solo cambiare il colore delle celle selezionate .Mantieni offset quando reloadRowsAtIndexPaths

Questo è quello che faccio nel cellForRowAtIndexPath:

SMPChoiceViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ChoiceCell" forIndexPath:indexPath]; 
SMPChoice *choice = self.choices[indexPath.row - 1]; 
cell.choiceTextLabel.text = choice.text; 

if ([self.selectedChoices indexOfObject:choice] != NSNotFound) { 
    cell.choiceTextLabel.textColor = [UIColor purpleColor]; 
} else { 
    cell.choiceTextLabel.textColor = [UIColor blackColor]; 
} 

e questo è quello che faccio nel didSelectRowAtIndexPath

if ([self.selectedChoices indexOfObject:choice] != NSNotFound) { 
    [self.selectedChoices removeObject:choice]; 
} else { 
    [self.selectedChoices addObject:choice]; 
} 

CGPoint offSet = [tableView contentOffset]; 

[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
[tableView setContentOffset:offSet animated:NO]; 

Ma salta solo, qualsiasi suggerimento?

P.S ho seguito questa discussione ma non ha risolto la mia domanda Calling reloadRowsAtIndexPaths removes tableView contentOffset

+1

Prova UITableViewRowAnimationNone e rimuovere [tableView setContentOffset: Offset animato: NO].; – Sathya

+0

Ciao Sathya ... Ancora scorre verso l'alto e ora non ha quel bel effetto di dissolvenza hehehe: '( – mtet88

risposta

8

So che questa è una vecchia questione, ma ho avuto questo stesso problema e non riusciva a trovare la risposta da nessuna parte.

Dopo il reloadRowsAtIndexPaths:withRowAnimation:, il TableView determina il relativo offset utilizzando le altezze stimate fornite in tableView:estimatedHeightForRowAtIndexPath:. Pertanto, a meno che il valore restituito non sia accurato, l'implementazione causerà la modifica dell'offset di TableView dopo il ricaricamento. Non ho implementato tableView:estimatedHeightForRowAtIndexPath: e il problema è stato risolto.

+0

Lo stato dei documenti: _ "Restituisci UITableViewAutomaticDimension se non hai stima" _ in 'tableView: estimatedHeightForRowAtIndexPath:' Si dovrebbe restituire quello invece di non implementarlo Un-implementazione del metodo causa alle celle un'altezza inaccurata –

+0

@ Gee.E UITableViewAutomaticDimension è stato introdotto in iOS 8. Quindi, se non si deve supportare nulla prima di iOS 8, quindi sì, dovresti usare UITableViewAutomaticDimension. Non sono sicuro del perché l'implementazione del metodo non funzioni per te. – eyuelt

+0

@ Gee.E anche restituendo UITableViewAutomaticDimension è solo un leggero miglioramento.Il TableView salta ancora in una posizione diversa. – lostintranslation

11

Perché per qualche misterioso motivo la vista tabella determina il nuovo offset dopo aver ricaricato alcune celle utilizzando l'altezza della riga stimata che si desidera assicurarsi che il valore tableView:estimatedHeightForRowAtIndexPath restituisca dati corretti per celle che sono già state visualizzate. Per fare questo è possibile memorizzare nella cache l'altezza delle righe visto in un dizionario, quindi utilizzare questi dati corretti (o la vostra stima per le celle non già caricati.)

fileprivate var heightForIndexPath = [NSIndexPath: CGFloat]() 
fileprivate let averageRowHeight: CGFloat = 300 //your best estimate 

//UITableViewDelegate 

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    heightForIndexPath[indexPath] = cell.frame.height 
} 

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 
    return heightForIndexPath[indexPath] ?? averageRowHeight 
} 

(grazie enorme a eyuelt per l'intuizione che l'altezza delle righe stimato è utilizzato per determinare il nuovo offset)

+0

Ancora lo stesso problema anche con l'approccio memorizzato nella cache. –

+0

Questa è stata una soluzione rapida e semplice al problema per me. Nessuna quantità di sovrastima o sottovalutazione dell'altezza della cella sembrava funzionare in modo coerente. Ho anche cancellato la cache quando la tabella è stata ricaricata con nuovi dati. – Chadwick

0

versione OBJ-C della risposta di Daniel:

//rowHeightForIndexPath is an NSMutableDictionary 
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { 
    [self.rowHeightForIndexPath setObject:@(cell.frame.size.height) forKey:indexPath]; 
} 

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSNumber *cachedHeight = [self.rowHeightForIndexPath objectForKey:indexPath]; 

    return cachedHeight ? cachedHeight.floatValue : UITableViewAutomaticDimension; 
} 
Problemi correlati