2015-05-07 20 views
10

Ho un UITableView con una cella che è dimensionata dinamicamente per adattarsi a UITextView al suo interno. Ogni volta che viene digitata una chiave, la cella controlla se l'altezza calcolata è aumentata, come con una nuova linea, in modo che possa indicare alla tabella che l'altezza della cella deve essere ricalcolata. Lo faccio con questo codice.UITableView Scorre in alto nella cella Aggiorna

- (void) createNoteCellViewDidUpdate: (CreateNoteCell*) cell { 

    CGFloat newHeight = [self tableView:self.tableView heightForRowAtIndexPath:CreateNoteCellIndexPath]; 
    if (newHeight != CGRectGetHeight(cell.contentView.frame)) { 
     [self.tableView beginUpdates]; 
     [self.tableView endUpdates]; // <- HERE IS WHERE THE CONTENT OFFSET CHANGES 
    } 
} 

I limiti di ridimensionamento e tabella sono come previsto. Ma invece di animare solo il cambiamento di altezza, scorre anche verso l'alto. Questo può essere visto qui, quando si preme il tasto Invio.

table scrolling on cell resize

Con Chiave Valore Observing, ho scoperto che il contentOffset vista di scorrimento viene impostata quando cambia contentSize della vista di scorrimento. E che contentSize cambia molte volte quando viene chiamato il metodo endUpdates. Quando cambia, passa da un'altezza normale a un'altezza piuttosto grande, quindi torna a un'altezza normale. Mi chiedo se per questo andrà a finire. Non so da dove andare.

+0

Domanda: perché stai tentando di ridimensionare il tuo tableview invece di ridimensionare la cella? Normalmente il frame di un tableview rimane costante e le modifiche del contenuto. – Frankie

+1

No, non sto toccando il frame oi limiti di Table View.Sto ridimensionando la cella dicendo alla vista tabella per ricalcolare tutte le altezze delle celle. – Jadar

risposta

22

Wow, la risposta di Josh Gafni ha aiutato molto; si merita un upvote. La mia soluzione è basata sulla sua. Questo sembra ancora un hack, quindi se qualcuno ha ancora un modo migliore per farlo, sono comunque molto interessato a sentirlo.

Prima di tutto, salvo lo spostamento del contenuto, quindi avvio l'aggiornamento.

CGPoint offset = self.tableView.contentOffset; 
[self.tableView beginUpdates]; 
[self.tableView endUpdates]; 

Questa anima la variazione di altezza della cella e regola tutti i fotogrammi per soddisfare i vincoli.

Successivamente rimuovo tutte le animazioni dal livello di tableView, così l'animazione verso l'alto si ferma. Quindi ho resettato il contenutoOffst a quello che era prima.

[self.tableView.layer removeAllAnimations]; 
[self.tableView setContentOffset:offset animated:NO]; 

Infine, lasciare che il tableView gestire la pergamena animata verso il basso in modo che il fondo della cella è proprio sopra la tastiera.

[self.tableView scrollToRowAtIndexPath:CreateNoteCellIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; 

E voilà, funziona piuttosto bene.

fixed cell resize

+0

Ho avuto quasi lo stesso problema, ma finora non ho avuto fortuna a far funzionare questa soluzione. Mi stavo chiedendo, stai facendo qualcosa per assicurarti che la tua cella UITextView appaia sopra la tastiera (ad esempio aggiornando contentInset)? Inoltre, hai trovato dei miglioramenti a questa soluzione? Grazie! – Stoph

+0

GRAZIE, proprio quello di cui avevo bisogno. –

+0

Davvero bella soluzione, grazie Josh e Jadar – Atrash

7

Solo una supposizione ...

Salvare il contentOffset del UITableView prima di eventuali modifiche. Quindi impostalo nuovamente dopo.

CGFloat contentOffset = self.tableView.contentOffset; 

e poi, dopo le modifiche

self.tableView.contentOffset = contentOffset; 
+0

Sì, ma questo ha il problema in cui contentOffset viene impostato da ScrollView, quindi impostato da me. Quindi l'animazione inizia a portarlo in cima, poi arrivo a metà dell'animazione e la porto indietro. Quindi si anima, poi in basso, il che diventa molto fastidioso dopo che l'altezza occupa tutto lo schermo. – Jadar

+1

Un pensiero (un po 'un trucco) potrebbe essere quello di sottoclasse tableView e sovrascrivere 'setContentOffset'. il 'contentOffset' deve essere impostato su 0 ad un certo punto per il verificarsi del salto. Aggiungi una proprietà bool a tableview chiamata 'isUpdatingCellHeight' e solo quando questa variabile è' NO' si aggiorna in realtà '_contentOffset'. Quindi, prima di aggiornare la tabella, impostalo su "YES" e dopo impostalo su "NO" e quindi setta "contentOffset" come menzionato sopra. –

+0

Il tuo primo modo con alcuni trucchi per cancellare l'animazione ha funzionato. Penso che sia un po 'più elegante della sottoclasse. Non voglio limitarlo dalle normali operazioni di regolazione dell'altezza della cella, solo in questo caso è necessario invertirlo. – Jadar

3

soluzione più semplice (aggiungere notifica osservatore quando textView viene modificato), Swift-versione. Il trucco principale sta usando UIView.setAnimationsEnabled.

func textViewDidChanged(notification: NSNotification) { 
    UIView.setAnimationsEnabled(false) 

    let contentOffset = self.tableView.contentOffset 

    tableView.beginUpdates() 
    tableView.endUpdates() 

    tableView.contentOffset = contentOffset 

    UIView.setAnimationsEnabled(true) 
} 
+0

Interessante, non sapevo che quel metodo esistesse. Grazie! – Jadar

+0

@Jadar, grazie, se quel metodo funziona e più semplice quella soluzione originale, contrassegnala come risposta. Se è stato utile, puoi almeno votarlo, in modo che altri utenti possano trovarlo facilmente. – Vasily

+0

Attualmente non ho un mezzo per testarlo poiché non sto più usando questo frammento di interfaccia utente. Sarei più propenso a farlo se avessi più commenti che spiegano come la risposta attualmente accettata. – Jadar

7

Ecco la mia estensione UITableView che funziona perfettamente. In Swift 2.1. Basato sulla risposta accettata.

extension UITableView 
{ 
    func reloadDataAnimatedKeepingOffset() 
    { 
     let offset = contentOffset 
     UIView.setAnimationsEnabled(false) 
     beginUpdates() 
     endUpdates() 
     UIView.setAnimationsEnabled(true) 
     layoutIfNeeded() 
     contentOffset = offset 
    } 
} 
+0

semplicemente fantastico! Grazie!!!! – Potajedehabichuelas

Problemi correlati