Czuję, że może to być powszechny problem i zastanawiałem się, czy istnieje jakieś wspólne rozwiązanie tego problemu.
Zasadniczo mój UITableView ma dynamiczne wysokości komórek dla każdej komórki. Jeśli nie jestem na górze UITableView i ja tableView.reloadData()
, przewijanie w górę staje się skokowe.
Uważam, że wynika to z faktu, że ponieważ ponownie ładowałem dane, gdy przewijam w górę, UITableView ponownie oblicza wysokość każdej komórki, która staje się widoczna. Jak to złagodzić lub jak mogę tylko przeładować dane z określonego IndexPath na koniec UITableView?
Co więcej, kiedy uda mi się przewinąć całą drogę do góry, mogę przewijać z powrotem w dół, a następnie w górę, bez problemu bez przeskakiwania. Jest to najprawdopodobniej spowodowane już obliczeniem wysokości UITableViewCell.
źródło
reloadRowsAtIndexPaths
. Ale (2) co masz na myśli przez „skokowy” i (3) czy ustawiłeś szacowaną wysokość wiersza? (Próbuję tylko dowiedzieć się, czy istnieje lepsze rozwiązanie, które pozwoliłoby dynamicznie aktualizować tabelę.)x
do ostatniego wiersza w moim TableView ... ale ponieważ wstawiam nowe wiersze, to nie zadziała, nie mogę wiedzieć, jaki będzie koniec mojego widoku tabeli przed ponownym załadowaniem dane.Odpowiedzi:
Aby zapobiec skokom, należy zapisać wysokość komórek podczas ich ładowania i podać dokładną wartość w
tableView:estimatedHeightForRowAtIndexPath
:Szybki:
Cel C:
źródło
cellHeightsDictionary
:cellHeightsDictionary = [NSMutableDictionary dictionary];
estimatedHeightForRowAtIndexPath:
zwraca podwójną wartość może spowodować*** Assertion failure in -[UISectionRowData refreshWithSection:tableView:tableViewRowData:]
błąd.return floorf(height.floatValue);
Zamiast tego , żeby to naprawić .Szybka 3 wersja zaakceptowanej odpowiedzi.
źródło
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
, która obsługuje wszystkie obliczenia wysokości, których potrzebuję.UITableViewDelegate
do swojej klasy. Zgodność z tym protokołem jest konieczna, ponieważ zawiera on powyższąwillDisplay
funkcję. Mam nadzieję, że uda mi się uratować komuś tę samą walkę.Skok jest spowodowany złą oceną wysokości. Im bardziej szacunkowa wysokośćRowHeight różni się od rzeczywistej wysokości, tym bardziej tabela może podskakiwać po przeładowaniu, zwłaszcza im dalej w dół została przewinięta. Dzieje się tak, ponieważ szacowany rozmiar tabeli radykalnie różni się od jej rzeczywistego rozmiaru, co wymusza na tabeli dostosowanie rozmiaru zawartości i przesunięcia. Więc szacowana wysokość nie powinna być wartością przypadkową, ale zbliżoną do tego, co myślisz, że będzie. Doświadczyłem również, kiedy ustawiam,
UITableViewAutomaticDimension
czy twoje komórki są wtedy tego samego typujeśli masz różne komórki w różnych sekcjach, myślę, że jest lepsze miejsce
źródło
tableView(_:estimatedHeightForHeaderInSection:)
@Igor odpowiedź działa dobrze w tym przypadku,
Swift-4
kod.w następujących metodach
UITableViewDelegate
źródło
Wypróbowałem wszystkie powyższe obejścia, ale nic nie działało.
Po spędzeniu wielu godzin i przejściu przez wszystkie możliwe frustracje, wymyśliłem sposób, aby to naprawić. To rozwiązanie ratuje życie! Działał jak urok!
Szybki 4
Dodałem go jako rozszerzenie, aby kod wyglądał bardziej przejrzysto i unikałem pisania tych wszystkich wierszy za każdym razem, gdy chcę przeładować.
Wreszcie ..
LUB możesz dodać te linie do swojej
UITableViewCell
awakeFromNib()
metodyi normalnie
reloadData()
źródło
reloadWithoutAnimation
, ale gdzie jestreload
część?tableView.reloadData()
najpierw zadzwonić, a potemtableView.reloadWithoutAnimation()
nadal działa.Używam więcej sposobów, jak to naprawić:
W przypadku kontrolera widoku:
jako rozszerzenie dla UITableView
Wynik to
źródło
Wpadłem na to dzisiaj i zauważyłem:
cellForRowAtIndexPath
nie pomaga.Poprawka była całkiem prosta:
Zastąp
estimatedHeightForRowAtIndexPath
i upewnij się, że zwraca prawidłowe wartości.Dzięki temu wszystkie dziwne drgania i skakanie w moich UITableViews ustały.
UWAGA: Właściwie znam rozmiar moich komórek. Istnieją tylko dwie możliwe wartości. Jeśli twoje komórki mają naprawdę zmienną wielkość, możesz chcieć buforować plik
cell.bounds.size.height
fromtableView:willDisplayCell:forRowAtIndexPath:
źródło
W rzeczywistości możesz przeładować tylko niektóre wiersze za pomocą
reloadRowsAtIndexPaths
, na przykład:Ale ogólnie możesz także animować zmiany wysokości komórek tabeli w następujący sposób:
źródło
Oto nieco krótsza wersja:
źródło
Zastępowanie metodyimateHeightForRowAtIndexPath wysoką wartością, na przykład 300f
To powinno rozwiązać problem :)
źródło
Jest błąd, który, jak sądzę, został wprowadzony w iOS11.
Dzieje się tak, gdy robisz, a
reload
tableViewcontentOffSet
zostaje nieoczekiwanie zmienione. W rzeczywistościcontentOffset
nie powinno się zmieniać po przeładowaniu. Zwykle dzieje się tak z powodu błędnych obliczeńUITableViewAutomaticDimension
Musisz zapisać swoją
contentOffSet
wartość i ustawić ją z powrotem na zapisaną wartość po zakończeniu przeładowania.Jak tego używasz?
Ta odpowiedź pochodzi stąd
źródło
Ten pracował dla mnie w Swift4:
źródło
Żadne z tych rozwiązań nie działało dla mnie. Oto, co zrobiłem ze Swift 4 i Xcode 10.1 ...
W viewDidLoad () zadeklaruj dynamiczną wysokość wiersza tabeli i utwórz poprawne ograniczenia w komórkach ...
Również w viewDidLoad () zarejestruj wszystkie końcówki komórek tableView w widoku tabeli w następujący sposób:
W tableView heightForRowAt zwraca wysokość równą wysokości każdej komórki w indexPath.row ...
Teraz podaj szacowaną wysokość wiersza dla każdej komórki w tableView EstymatedHeightForRowAt. Bądź dokładny, jak potrafisz ...
To powinno działać...
Nie musiałem zapisywać i ustawiać contentOffset podczas wywoływania tableView.reloadData ()
źródło
Mam 2 różne wysokości komórek.
Po dodaniu szacunkowej ocenyHeightForRowAt nie było więcej skoków.
źródło
Spróbuj zadzwonić
cell.layoutSubviews()
przed powrotem do komórkifunc cellForRowAtIndexPath(_ indexPath: NSIndexPath) -> UITableViewCell?
. To znany błąd w iOS8.źródło
Możesz użyć następujących w
ViewDidLoad()
źródło
Miałem to zachowanie związane z skokami i początkowo byłem w stanie je złagodzić, ustawiając dokładną szacowaną wysokość nagłówka (ponieważ miałem tylko 1 możliwy widok nagłówka), jednak skoki zaczęły się wtedy pojawiać szczególnie wewnątrz nagłówków, nie wpływając już na całą tabelę.
Podążając za odpowiedziami tutaj, miałem wskazówkę, że jest to związane z animacjami, więc odkryłem, że widok tabeli znajduje się wewnątrz widoku stosu, a czasami wywoływaliśmy
stackView.layoutIfNeeded()
wewnątrz bloku animacji. Ostatnim rozwiązaniem było upewnienie się, że to wywołanie nie nastąpi, chyba że jest to „naprawdę” potrzebne, ponieważ układ „w razie potrzeby” zachowuje się wizualnie w tym kontekście, nawet gdy „nie jest potrzebny”.źródło
Miałem ten sam problem. Miałem paginację i ponowne ładowanie danych bez animacji, ale nie pomogło to przewijaniu zapobiec przeskakiwaniu. Mam różne rozmiary iPhone'ów, przewijanie nie było skokowe na iphone8, ale na iphone7 +
Zastosowałem następujące zmiany w funkcji viewDidLoad :
i mój problem został rozwiązany. Mam nadzieję, że tobie też pomoże.
źródło
Jednym ze sposobów rozwiązania tego problemu, które znalazłem, jest
źródło
Właściwie znalazłem, jeśli używasz
reloadRows
powodując problem ze skokiem. Następnie powinieneś spróbować użyć wreloadSections
ten sposób:źródło