2016-01-12 4 views
8

Wie kann man Zeilen ganz oben in einen UITableView einfügen, ohne dass der Rest der Zellen nach unten gedrückt wird - so scheint sich die Bildlaufposition nicht zu ändern überhaupt?Einfügen von Zeilen am oberen Rand von UITableView ohne Änderung der Bildlaufposition bei Verwendung von UITableViewAutomaticDimension

Genau wie Facebook und Twitter, wenn neue Posts geliefert werden, werden sie oben eingefügt, aber die Scroll-Position bleibt fest.

Meine Frage ist ähnlich dieser this question. Was meine Frage von dieser Frage unterscheidet, ist, dass ich keine Tabelle mit festen Zeilenhöhen verwende - ich verwende UITableViewAutomaticDimension und eine estimatedRowHeight. Daher werden die dort vorgeschlagenen Antworten nicht funktionieren, da ich die Zeilenhöhe nicht bestimmen kann.

Ich habe versucht, diese Lösung, die Zeilenhöhe nicht in Betracht zieht, aber die contentSize ist immer noch nicht korrekt nach dem Neuladen, weil die contentOffset nicht die gleiche relative Position ist - die Zellen sind immer noch nach unten gedrückt wo Sie waren vor dem Einsatz. Dies liegt daran, dass die Zelle nicht auf dem Bildschirm gerendert wurde, sodass iOS die entsprechende Höhe nicht berechnet, bis es erscheint. Daher ist contentSize nicht korrekt.

CGSize beforeContentSize = tableView.contentSize; 
[tableView reloadData]; 
CGSize afterContentSize = tableView.contentSize; 
CGPoint afterContentOffset = tableView.contentOffset; 
tableView.contentOffset = CGPointMake(afterContentOffset.x, afterContentOffset.y + afterContentSize.height - beforeContentSize.height); 

Alain hingewiesen rectForCellAtIndexPath die IOS zwingt die entsprechende Höhe zu berechnen. Ich kann jetzt die richtige Höhe für die eingefügten Zellen bestimmen, aber die Scroll-Ansicht contentSize ist immer noch nicht korrekt, wie belegt, wenn ich über alle Zellen iteriere und addiere die Höhen, die größer als contentSize.height ist. Letztendlich, wenn ich den contentOffset manuell setze, scrollt er nicht zum richtigen Ort.

Originalcode:

//update data source 
[tableView beginUpdates]; 
[tableView insertRowsAtIndexPaths:newIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic]; 
[tableView endUpdates]; 

In diesem Szenario kann, was das gewünschte Verhalten zu erreichen getan werden?

+0

Haben Sie eine Lösung gefunden? –

+0

@AndreyGordeev Nein. Ich verwendete die geschätzte Zeilenhöhe nicht mehr und berechnete manuell die erforderliche Höhe für jede Zeile. – Joey

+0

Wie haben Sie es geschafft, mit dem falschen ContentSize-Problem umzugehen? – goldengil

Antwort

0

Ich denke, Ihre Lösung war fast da. Sie sollten den neuen Y-Offset auf den "vorher" Y-Offset und nicht auf den "nach" setzen.

..., beforeContentOffset.y + afterContentSize.height - beforeContentSize.height

+0

Dies hat den Trick nicht gemacht. Aufgrund der Komplexität bei der Berechnung der korrekten Inhaltsgröße bei Verwendung dynamischer Zeilenhöhen wird dies wahrscheinlich immer noch unterdrückt. – Joey

+0

Vielleicht würde dies mit Ihrem ursprünglichen Code besser funktionieren. Mein Gefühl ist, dass Sie ein Ereignis finden müssen, das ausgelöst wird, nachdem die Zelle rendering/Berechnungen abgeschlossen sind, um den Offset neu zu positionieren, wie dedEndDisplayingCell zum Beispiel oder auf einem Timer. –

+0

Dies würde zu einem Flash führen . Wenn ich eine Zelle einfüge, wird sie sie sofort einfügen und die Zellen neu positionieren, dann setze ich den Inhalt nach einiger Zeit wieder auf, um zurück zu springen, wo sie waren, wird es ziemlich auffallen. – Joey

1

Auch einreihige Abschnitte gewünscht, kann (Sie beforeContentOffset Punkt vor dem Reload-Daten allerdings speichern müssten) erreichen Wirkung

Wenn ein Abschnitt bereits an der angegebenen Indexposition existiert, wird er um eine Indexposition nach unten verschoben. https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/index.html#//apple_ref/occ/instm/UITableView/insertSections:withRowAnimation :

let idxSet = NSIndexSet(index: 0) 
self.verseTable.insertSections(idxSet, withRowAnimation: .Fade) 
1

Treffen Sie das gleiche Problem und immer noch nicht finden, eine elegante Art und Weise it.Here ist meine Art und Weise zu lösen, nehme ich an moreData.count Zellen über der aktuellen Zelle eingefügt werden soll.

// insert the new data to self.data 
for (NSInteger i = moreData.count-1; i >= 0; i--) { 
    [self.data insertObject:moreData[i] atIndex:0]; 
} 

//reload data or insert row at indexPaths 
[self.tableView reloadData]; 

//after 0.1s invoke scrollToRowAtIndexPath:atScrollPosition:animated: 
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:moreData.count inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; 
}); 

Der Vorteil ist die Position vor und nach dem Einfügen neuer Daten behoben.Der Nachteil ist, wir können den Bildschirm blinken sehen (die oberste Zelle zeigt und nach oben)

6

Spät in die Partei, aber das funktioniert auch wenn Zelle dynamische Höhen haben (aka UITableViewAutomaticDimension), müssen nicht über Zellen durchlaufen, um ihre Größe zu berechnen , funktioniert aber nur, wenn Elemente ganz am Anfang der Tabelle hinzugefügt werden, und es gibt keine Überschrift, mit ein wenig Mathematik ist es wahrscheinlich möglich, dies an jede Situation anzupassen:

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
     if indexPath.row == 0 { 
      self.getMoreMessages() 
     } 
} 

private func getMoreMessages(){ 
     var initialOffset = self.tableView.contentOffset.y 
     self.tableView.reloadData() 
     //@numberOfCellsAdded: number of items added at top of the table 
     self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: numberOfCellsAdded, inSection: 0), atScrollPosition: .Top, animated: false) 
     self.tableView.contentOffset.y += initialOffset 
} 
+2

Dies ist die einzige Lösung, die mir helfen kann von den vielen, die bereits da draußen sind! Es gibt jedoch ein Problem: Das Inertial Scrolling wird sofort beendet. Gibt es eine Möglichkeit, die aktuelle Scrollgeschwindigkeit beizubehalten? – Nickkk

+0

Ich konnte das noch nicht lösen, wenn Sie eine Lösung finden, lassen Sie es mich wissen – Ezechiele

Verwandte Themen