У меня есть UITableView
пользовательский, UITableViewCell
определенный в раскадровке с использованием автоматического макета. Ячейка имеет несколько многострочных UILabels
.
В по- UITableView
видимому, правильно CALCulate высоты клеток, но в течение первых нескольких клеток , что высота не должным образом разделена между этикетками. После небольшой прокрутки все работает как положено (даже ячейки, которые изначально были неверными).
- (void)viewDidLoad {
[super viewDidLoad]
// ...
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
// ...
// Set label.text for variable length string.
return cell;
}
Есть ли что-то, чего мне может не хватать, из-за чего автоматический макет не может выполнять свою работу первые несколько раз?
Я создал образец проекта, демонстрирующий это поведение.
Ответы:
Я не знаю, четко это задокументировано или нет, но добавление
[cell layoutIfNeeded]
ячейки перед возвратом решает вашу проблему.источник
-layoutIfNeeded
в ячейку-awakeFromNib
. Я бы предпочел звонить только тогда,layoutIfNeeded
когда знаю, зачем это нужно.Это сработало для меня, когда другие подобные решения не работали:
Это похоже на настоящую ошибку, поскольку я очень хорошо знаком с AutoLayout и тем, как использовать UITableViewAutomaticDimension, однако я все еще иногда сталкиваюсь с этой проблемой. Я рад, что наконец нашел что-то, что работает как обходной путь.
источник
super.didMoveToSuperview()
didMoveToSuperview
: «Реализация этого метода по умолчанию ничего не делает».Добавление
[cell layoutIfNeeded]
вcellForRowAtIndexPath
не работает для клеток, которые первоначально прокручивается вне зрения.И не делает это в начале
[cell setNeedsLayout]
.Вам все равно придется прокручивать определенные ячейки назад и обратно, чтобы их размер изменился правильно.
Это довольно неприятно, поскольку у большинства разработчиков корректно работают Dynamic Type, AutoLayout и Self-Sizing Cells - за исключением этого раздражающего случая. Эта ошибка затрагивает все мои "более высокие" контроллеры табличного представления.
источник
[cell layoutSubviews]
вместо layoutIfNeeded могло бы стать возможным исправлением. Обратитесь к stackoverflow.com/a/33515872/1474113У меня был такой же опыт в одном из моих проектов.
Почему это происходит?
Ячейка разработана в Раскадровке с некоторой шириной для какого-то устройства. Например 400 пикселей. Например, ваша этикетка имеет одинаковую ширину. Когда он загружается из раскадровки, он имеет ширину 400 пикселей.
Вот проблема:
tableView:heightForRowAtIndexPath:
вызывается перед макетом ячейки, это подвиды.Таким образом, он рассчитал высоту для метки и ячейки шириной 400 пикселей. Но вы работаете на устройстве с экраном, например, 320 пикселей. И эта автоматически рассчитанная высота неверна. Просто потому, что ячейка
layoutSubviews
происходит только после того, какtableView:heightForRowAtIndexPath:
даже если вы установитеpreferredMaxLayoutWidth
для своей метки вручную,layoutSubviews
это не помогает.Мое решение:
1) Подкласс
UITableView
и переопределениеdequeueReusableCellWithIdentifier:forIndexPath:
. Установите ширину ячейки равной ширине таблицы и задайте макет ячейки.2) Подкласс
UITableViewCell
. УстановитеpreferredMaxLayoutWidth
вручную для ваших этикеток в форматеlayoutSubviews
. Также вам нужна ручная компоновкаcontentView
, потому что она не компоновка автоматически после изменения кадра ячейки (я не знаю почему, но это так)источник
cell.frame.size.width = tableview.frame.width
тоcell.layoutIfNeeded()
вcellForRowAt
функции сделал трюк для меняУ меня аналогичная проблема, при первой загрузке высота строки не рассчитывалась, но после некоторой прокрутки или перехода на другой экран, и я возвращаюсь к этому экрану, строки вычисляются. При первой загрузке мои элементы загружаются из Интернета, а при второй загрузке мои элементы загружаются сначала из Core Data и перезагружаются из Интернета, и я заметил, что высота строк рассчитывается при перезагрузке из Интернета. Итак, я заметил, что когда tableView.reloadData () вызывается во время анимации перехода (такая же проблема с push и текущим переходом), высота строки не вычисляется. Поэтому я спрятал tableview при инициализации представления и поставил загрузчик активности, чтобы предотвратить неприятный эффект для пользователя, и я вызываю tableView.reloadData через 300 мс, и теперь проблема решена. Я думаю, что это ошибка UIKit, но этот обходной путь поможет.
Я помещаю эти строки (Swift 3.0) в обработчик завершения загрузки элемента
Это объясняет, почему некоторые люди помещают reloadData в layoutSubviews, чтобы решить проблему.
источник
Ни одно из вышеперечисленных решений у меня не сработало, сработал этот рецепт волшебства: назовите их в таком порядке:
tableView.reloadData()
tableView.layoutIfNeeded() tableView.beginUpdates() tableView.endUpdates()
мои данные tableView заполняются из веб-службы, при обратном вызове соединения я пишу приведенные выше строки.
источник
В моем случае последняя строка UILabel была усечена, когда ячейка отображалась в первый раз. Это произошло довольно случайно, и единственный способ правильно определить размер - вывести ячейку из поля зрения и вернуть ее обратно. Я пробовал все возможные решения, представленные до сих пор (layoutIfNeeded..reloadData), но у меня ничего не сработало. Хитрость заключалась в наборе «Autoshrink» в Minimuum шрифта Scale (0.5 для меня). Попробуйте
источник
Добавьте ограничение для всего содержимого в пользовательской ячейке табличного представления, затем оцените высоту строки табличного представления и установите для высоты строки автоматический размер с загрузкой viewdid:
Чтобы исправить эту проблему с начальной загрузкой, примените метод layoutIfNeeded в ячейке настраиваемого табличного представления:
источник
estimatedRowHeight
значение> 0, а неUITableViewAutomaticDimension
(то есть -1), иначе автоматическая высота строки не будет работать.Я попробовал ответить на большинство ответов на этот вопрос и не смог заставить работать ни один из них. Единственное функциональное решение, которое я нашел, - это добавить к моему
UITableViewController
подклассу следующее:UIView.performWithoutAnimation
Требуется вызов, в противном случае вы увидите обычную таблицу анимации нагрузок вида контроллера.источник
viewWillAppear
не работает для меня, но делать это вviewDidAppear
сделал.preferredMaxLayoutWidth
В моем случае настройка помогает. я добавилв моем коде.
Также см. Однострочный текст занимает две строки в UILabel и http://openradar.appspot.com/17799811 .
источник
звонок
cell.layoutIfNeeded()
внутрьcellForRowAt
работал у меня на ios 10 и ios 11, но не на ios 9.Чтобы получить эту работу и на ios 9, я позвонил,
cell.layoutSubviews()
и это помогло.источник
Для меня ни один из этих подходов не работал, но я обнаружил, что метка явно
Preferred Width
задана в Interface Builder. Удаление этого (снятие флажка «Явный») и последующее использованиеUITableViewAutomaticDimension
сработало, как ожидалось.источник
Я попробовал все решения на этой странице, но снятие флажка с использованием классов размеров и повторная проверка решило мою проблему.
Изменить: снятие отметки с классов размеров вызывает множество проблем на раскадровке, поэтому я попробовал другое решение. Я заполнил свое табличное представление в контроллерах
viewDidLoad
иviewWillAppear
методах представления. Это решило мою проблему.источник
У меня проблема с изменением размера метки, поэтому мне нужно просто сделать
chatTextLabel.text = chatMessage.message chatTextLabel? .UpdateConstraints () после настройки текста
// полный код
источник
В моем случае я обновлялся в другом цикле. Таким образом, высота tableViewCell была обновлена после установки labelText. Я удалил асинхронный блок.
источник
Просто убедитесь, что вы не устанавливаете текст метки в методе делегата willdisplaycell представления таблицы. Задайте текст метки в методе делегата cellForRowAtindexPath для динамического расчета высоты.
Пожалуйста :)
источник
В моем случае проблема была в представлении стека в ячейке. Очевидно, это ошибка. Как только я его удалил, проблема была решена.
источник
Проблема в том, что начальные ячейки загружаются до того, как у нас будет допустимая высота строки. Обходной путь - принудительно перезагрузить таблицу при появлении представления.
источник
Только для iOS 12+, начиная с 2019 г. ...
Постоянный пример периодической странной некомпетентности Apple, когда проблемы длятся буквально годами.
Похоже, что
исправлю это. (Вы, конечно, теряете производительность.)
Такова жизнь с Apple.
источник
В моем случае проблема с высотой ячейки возникает после загрузки начального представления таблицы и выполнения действия пользователя (нажатие кнопки в ячейке, что приводит к изменению высоты ячейки). Мне не удалось изменить высоту ячейки, если я этого не сделаю:
Я действительно пробовал
но это не сработало.
источник
В Swift 3. Мне приходилось вызывать self.layoutIfNeeded () каждый раз, когда я обновляю текст повторно используемой ячейки.
источник
Ни одно из вышеперечисленных решений не помогло, но сработала следующая комбинация предложений.
Пришлось добавить следующее в viewDidLoad ().
Вышеупомянутая комбинация reloadData, setNeedsLayout и layoutIfNeeded работала, но не другие. Однако может быть специфическим для ячеек в проекте. И да, пришлось дважды вызывать reloadData, чтобы он заработал.
Также установите следующее в viewDidLoad
В tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
источник
reloadData/beginUpdates/endUpdates/reloadData
тоже работает;reloadData
нужно позвонить во второй раз. Не нужно заворачиватьasync
.Я столкнулся с этой проблемой и исправил ее, переместив код инициализации представления / метки ОТ
tableView(willDisplay cell:)
ДОtableView(cellForRowAt:)
.источник
willDisplay
будет иметь лучшую производительность, чемcellForRowAt
. Используйте самую последнюю только для создания нужной ячейки.willDisplay
вас лучшая производительность, рекомендуется инициализировать пользовательский интерфейс ячейки,cellForRowAt
когда макет является автоматическим. Действительно, макет вычисляется UIKit после cellForRowAt и до willDisplay. Поэтому, если высота вашей ячейки зависит от ее содержимого, инициализируйте содержимое метки (или что-то еще) вcellForRowAt
.используйте указанный выше метод, который динамически возвращает высоту строки. И назначьте ту же динамическую высоту ярлыку, который вы используете.
Этот код помогает вам найти динамическую высоту для отображения текста на этикетке.
источник