2015-05-07 16 views
10

Ich habe eine UITableView mit einer Zelle, die dynamisch an ein UITextView darin passt. Immer wenn ein Schlüssel eingegeben wird, überprüft die Zelle, ob die berechnete Höhe wie bei einem Zeilenumbruch zugenommen hat, so dass die Zelle die Höhe der Zelle neu berechnen muss. Ich mache das mit diesem Code.UITableView Scrollt nach oben bei Zellenaktualisierung

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

Die Größenänderung und Tabellengrenzen sind wie erwartet. Aber anstatt nur die Änderung der Höhe zu animieren, scrollt es auch nach oben. Dies ist hier zu sehen, wenn die Eingabetaste gedrückt wird.

table scrolling on cell resize

von Key Value Observing, ich habe die Scroll-Ansicht Content, dass, wenn die Content Änderungen Scroll-Ansicht des eingestellt herausgefunden wird. Und das contentSize ändert sich oft, wenn die Methode endUpdates aufgerufen wird. Wenn es sich ändert, geht es von einer normalen Höhe zu einer ziemlich großen Höhe, dann zurück zu einer normalen Höhe. Ich frage mich, ob es darum geht. Ich weiß nicht, wo ich von hier aus hingehen soll.

+0

Frage - warum versuchen Sie, Ihre Tabellenansicht zu skalieren, anstatt nur die Größe der Zelle zu ändern? Normalerweise bleibt der Rahmen einer Tabellenansicht konstant und ändert sich inhaltlich. – Frankie

+1

Nein, ich berühre nicht den Rahmen oder die Grenzen der Tabellenansicht.Ich ändere die Größe der Zelle, indem ich der Tabellenansicht erzähle, alle Höhen der Zellen neu zu berechnen. – Jadar

Antwort

22

Wow, Antwort Josh Gafni hat viel dazu beigetragen; er verdient eine Erwiderung. Meine Lösung basiert auf seiner. Das fühlt sich immer noch wie ein Hack an. Wenn jemand noch einen besseren Weg hat, dies zu tun, bin ich immer noch sehr interessiert, es zu hören.

Zuerst speichere ich den Inhalt Offset, dann starte ich das Update.

Dies animiert die Höhenänderung der Zelle und passt alle Rahmen an die Einschränkungen an.

Als nächstes entferne ich alle Animationen aus der Ebene des TableView, so dass die Animation nach oben stoppt. Dann setze ich das contentOffst auf das zurück, was es vorher war.

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

Schließlich möchte ich die Tableview die animierte nach unten scrollen handhaben, so dass die Unterseite der Zelle rechts oberhalb der Tastatur ist.

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

Und voila, es funktioniert ziemlich gut.

fixed cell resize

+0

Ich habe fast genau das gleiche Problem gehabt, aber bisher hatte ich kein Glück, dass diese Lösung funktioniert. Ich habe mich gefragt, ob Sie etwas tun, um sicherzustellen, dass Ihre UITextView-Zelle über der Tastatur angezeigt wird (z. B. das contentInset aktualisieren)? Haben Sie auch Verbesserungen an dieser Lösung gefunden? Vielen Dank! – Stoph

+0

DANKE, was ich brauchte. –

+0

Wirklich nette Lösung, danke Josh und Jadar – Atrash

7

Nur eine Vermutung ...

Speichern Sie die contentOffset des UITableView vor Änderungen. Stellen Sie es danach erneut ein.

CGFloat contentOffset = self.tableView.contentOffset; 

und dann nach den Änderungen

self.tableView.contentOffset = contentOffset; 
+0

Ja, aber das hat das Problem, wo der ContentOffset von der ScrollView gesetzt und dann von mir gesetzt wird. Die Animation beginnt also, sie an die Spitze zu bringen, dann komme ich mitten in die Animation und bringe sie zurück. Es animiert also nach oben, dann nach unten, was sehr ärgerlich wird, wenn die Höhe den ganzen Bildschirm einnimmt. – Jadar

+1

Ein Gedanke (ein bisschen ein Hack) könnte sein, tableView abzuleiten und 'setContentOffset' zu überschreiben. Das 'contentOffset' muss an irgendeinem Punkt auf 0 gesetzt werden, damit der Sprung stattfinden kann. Fügen Sie der Tabellenansicht 'isUpdatingCellHeight' eine bool-Eigenschaft hinzu, und nur wenn diese Variable' NO' ist, wird '_contentOffset' tatsächlich aktualisiert. Bevor Sie also die Tabelle aktualisieren, stellen Sie sie auf "YES" und setzen Sie sie auf "NO" und setzen Sie dann "contentOffset", wie ich oben erwähnt habe. –

+0

Ihr erster Weg mit Trickbetrug-Tricks hat es funktioniert. Ich denke, es ist ein bisschen eleganter als Unterklassen. Ich möchte es nicht von seinen normalen Einstellungen für die Zellhöhenanpassung einschränken, nur in diesem einen Fall musste es umgekehrt werden. – Jadar

3

Weitere vereinfachte Lösung (Mitteilung Beobachter hinzufügen, wenn Textview geändert wird), Swift-Version. Haupttrick ist 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

Interessant, ich wusste nicht, dass diese Methode existiert. Vielen Dank! – Jadar

+0

@Jadar, danke, wenn diese Methode funktioniert und diese originelle Lösung vereinfacht, bitte als Antwort markieren. Wenn es hilfreich war, können Sie zumindest dafür stimmen, damit andere Benutzer es leicht finden können. – Vasily

+0

Ich habe derzeit keine Möglichkeit, es zu testen, da ich dieses Bit der Benutzeroberfläche nicht mehr verwende. Ich würde eher geneigt sein, dies zu tun, wenn Sie mehr Kommentare hätten, die die aktuell akzeptierte Antwort erklären. – Jadar

7

Hier ist meine UITableView-Erweiterung, die perfekt funktioniert. In Swift 2.1. Basierend auf der angenommenen Antwort.

+0

einfach unglaublich! Vielen Dank!!!! – Potajedehabichuelas

Verwandte Themen