Випуск динамічної висоти для клітин UITableView (Swift)


79

Динамічний текст змінної довжини вставляється в мітки комірок табличного перегляду. Для того, щоб висоти комірок табличного перегляду мали динамічний розмір, я реалізував у viewDidLoad():

self.tableView.estimatedRowHeight = 88.0
self.tableView.rowHeight = UITableViewAutomaticDimension

Це добре працює для комірок, до яких ще не потрібно прокрутити (як UITableViewAutomaticDimentionце називається при прокрутці до комірки), але не для комірок, які спочатку відображаються на екрані при завантаженні таблиці з даними.

Я спробував просто перезавантажити дані (як пропонується у багатьох інших ресурсах):

self.tableView.reloadData()

в обох viewDidAppear()і viewWillAppear()і це не дало результату. Я загубився .. хтось знає, як зробити так, щоб xcode відображав динамічну висоту для клітинок, завантажених спочатку на екран?

Будь ласка, дайте мені знати, якщо є кращий альтернативний метод.


Чи правильно встановлені ваші обмеження висоти для встановлення клітинок (клітин), я не бачив жодних проблем із цим у дикій природі, використовуючи версію Xcode 6.3. Навіть майте зразок проекту на github з цією роботою. github.com/darren102/DTFAutomaticCellHeight
darren102

1
Я вирішив цю проблему, перевиконавши потенційну висоту етикетки. Будь ласка, дивіться мою відповідь нижче. Незалежно від того, якщо у вас є краще рішення, будь ласка, дайте мені знати!
простота

Відповіді:


115

Спробуйте це:

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

РЕДАГУВАТИ

func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

Стрімкий 4

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

Свіфт 4.2

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}

Визначте вище обидва методи.
Це вирішує проблему.

PS: Для роботи потрібні верхні та нижні обмеження.

Ось приклад


3
@bashan Це чудово працює. Переконайтеся, що ви встановили належні обмеження.
iDhaval

2
Не працює. Здається, є помилка, якщо слово занадто довге, але недостатньо довге, воно не відображається належним чином. Якщо це кілька слів, це, здається, працює належним чином.
Jeeves

6
Це не працювало для мене, поки я не додав нижнє обмеження. Думаю, у вашій відповіді варто зазначити, що для того, щоб це працювало, потрібно встановити верхні та нижні обмеження.
Мітч Дауні,

2
Щоб це працювало, потрібні нижні та верхні контрасти.
Antony Ouseph

2
Для цього потрібні обмеження знизу та зверху для "елементів комірки"
EnasAZ,

37

Використовуй це:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300

і не використовувати: heightForRowAtIndexPathделегувати функцію

Крім того, в раскадровці не встановлюйте висоту мітки, що містить велику кількість даних. Дайте йому top, bottom, leading, trailingобмеження.


4
Нижнє обмеження важливо! Я пропустив це і здивувався, чому висоту не можна розрахувати.
coyer 04

Я залишав цеheightForRowAtIndexPath
Помилка сервера 500

@Javeed Я думаю, що ти можеш використовувати його де завгодно, наприклад, статичну комірку або динамічну комірку ..
ami rt

16

SWIFT 3

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160

І !!! У storyBoard: ВИ ПОВИННІ встановити обмеження TOP & BOTTOM для вашого ярлика. Більш нічого.


11

Ця дивна помилка була вирішена за допомогою параметрів Interface Builder, оскільки інші відповіді не вирішили проблему.

Все, що я зробив, це зробити розмір мітки за замовчуванням більшим, ніж потенційно міг би бути вміст, і також відобразити його на estimatedRowHeightвисоті. Раніше я встановив висоту рядка за замовчуванням у Interface Builder 88pxі відобразив це так у своєму контролері viewDidLoad():

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0

Але це не спрацювало. Тож я зрозумів, що вміст ніколи не стане більшим, ніж можливо 100px, тому встановив висоту комірки за замовчуванням 108px(більшу, ніж потенційний вміст) і відобразив це так само в контролері viewDidLoad():

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 108.0

Це фактично дозволило коду зменшити початкові мітки до правильного розміру. Іншими словами, він ніколи не розширювався до більшого розміру, але завжди міг зменшуватися ... Крім того, додаткові додатки self.tableView.reloadData()в viewWillAppear().

Я знаю, що це не охоплює сильно мінливі розміри вмісту, але це спрацювало в моїй ситуації, коли вміст мав максимально можливу кількість символів.

Не впевнений, що це помилка в Swift або Interface Builder, але це працює як принада. Спробувати!


У мене теж та сама проблема. Я оновив свою відповідь. це вирішило мою проблему. просто визначте лише цей метод і видаліть усі речі, пов’язані з висотою.
iDhaval

8

Встановіть автоматичний розмір для висоти рядка та передбачуваної висоти рядка та забезпечте наступні кроки:

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Set automatic dimensions for row height
    // Swift 4.2 onwards
    table.rowHeight = UITableView.automaticDimension
    table.estimatedRowHeight = UITableView.automaticDimension


    // Swift 4.1 and below
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension

}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    // Swift 4.2 onwards
    return UITableView.automaticDimension

    // Swift 4.1 and below
    return UITableViewAutomaticDimension
}

Наприклад: якщо у вас є мітка у вашому UITableviewCell,

  • Встановити кількість рядків = 0 (& режим розриву рядка = усіка хвоста)
  • Встановіть усі обмеження (зверху, знизу, праворуч ліворуч) щодо контейнера супервигляду / комірки.
  • Необов’язково : Встановіть мінімальну висоту для етикетки, якщо ви хочете, щоб мінімальна вертикальна площа, покрита етикеткою, навіть якщо немає даних.

Ось зразок мітки з динамічними обмеженнями висоти.

введіть тут опис зображення


1
Запис у ViewDidLoad (), згаданий Krunal, був для мене рішенням.
SHS

7

Для динамічного розміру комірки UITableView потрібно 2 речі

  1. Встановлення правильного обмеження вашого перегляду всередині комірки подання таблиці (здебільшого воно включає надання правильного перегляду верхнього, нижнього та тралінг-обмежень)
  2. Виклик цих властивостей TableView у viewDidLoad ()

     tableView.rowHeight = UITableViewAutomaticDimension
    
     tableView.estimatedRowHeight = 140
    

Це чудовий підручник з самостійного визначення розміру (динамічні комірки табличного подання), написаний швидко в 3.


6

Для Swift 3 ви можете використовувати наступне:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

3

Для Swift 4.2

@IBOutlet weak var tableVw: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Set self as tableView delegate
    tableVw.delegate = self

    tableVw.rowHeight = UITableView.automaticDimension
    tableVw.estimatedRowHeight = UITableView.automaticDimension
}

// UITableViewDelegate Method 
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    return UITableView.automaticDimension
}

Щасливого кодування :)


2

Спробуйте

override func viewWillAppear(animated: Bool) {
    self.tableView.layoutSubviews()
}

У мене була та сама проблема, і вона працює для мене.


Я спробую і дам вам знати, що відбувається. Дякую за пропозицію! Майже через рік після запитання я не знайшов жодної іншої відповіді, крім своєї! Сподіваюся, твої твори!
простота

не забудьте зателефонувати super.viewWillAppear (анімований) перед тим, як зателефонувати до макетів subviews
Алан Скарпа

2

Щоб зробити автоматичний розмір UITableViewCell для роботи, переконайтесь, що ви робите ці зміни:

  • У Storyboard ваш UITableView повинен містити лише динамічні клітини-прототипи (він не повинен використовувати статичні комірки), інакше авторозмір не буде працювати.
  • У сториборді UILabel вашого UITableViewCell налаштовано на всі 4 обмеження, тобто верхнє, нижнє, провідне та кінцеве обмеження.
  • У розкадровці кількість рядків UILabel вашого UITableViewCell повинна бути 0
  • У вашому UIViewController функція viewDidLoad, встановлена ​​нижче властивостей UITableView:

    self.tableView.estimatedRowHeight = <minimum cell height> 
    self.tableView.rowHeight = UITableViewAutomaticDimension
    

Як реалізувати те саме за допомогою статичних комірок?
Javeed

Спробувавши всі запропоновані тут рішення, лише це (встановивши <minimum cell height>для estimatedRowHeight) справді виправило мою проблему. До цього клітина зробила автоматичний розмір, але я також отримував різні попередження про обмеження. Зараз я ні! Тож, дякую тобі, Аншуле !!
RoberRM

2

Для Swift я перевірив цю відповідь у iOS 9.0 та iOS 11 також (Xcode 9.3)

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

Тут потрібно додати верхнє, нижнє, праве та ліве обмеження


2

У моєму випадку - у раскадровці я мав дві мітки, як на малюнку нижче, обидві мітки мали встановлені бажані значення ширини, перш ніж я зробив це рівним. як тільки ви скасуєте вибір, він зміниться на автоматичний, і, як зазвичай, наявність речей нижче має працювати як шарм.

1.rowHeight = UITableView.automaticDimension, and
2.estimatedRowHeight = 100(In my case).
3.make sure label number of lines is zero.

введіть тут опис зображення


2

На додаток до сказаного іншими,

ВСТАНОВИТЕ ОБМЕЖЕННЯ ВАШОЇ ЕТИКЕТКИ, ЩО ВІДНОСНУЮТЬСЯ ДО ОГЛЯДУ!

Отже, замість того, щоб розміщувати обмеження вашої мітки щодо інших речей навколо неї, обмежте її переглядом вмісту комірки подання таблиці.

Потім переконайтеся, що висоту вашої мітки встановлено більше або дорівнює 0, а кількість рядків - 0.

Потім ViewDidLoadдодайте:

tableView.estimatedRowHeight = 695

tableView.rowHeight = UITableViewAutomaticDimension

ВСТАНОВИТИ ОБМЕЖЕННЯ ВАШОЇ ЕТИКЕТКИ, ЩО ПОСІБНІ ДО ОГЛЯДУ! Дякую.
ACAkgul

2

Це просто, роблячи 2 речі:

  1. встановлення автоматичної висоти
tableView.rowHeight = UITableView.automaticDimension
  1. створення всіх таблиць TableViewCells з ПОВНИМИ обмеженнями зверху вниз. Останній елемент ПОВИНЕН визначити деякий інтервал внизу для закінчення комірки.

Тож механізм компонування може обчислити висоту комірки та правильно застосувати значення.


1

Я просто надихнувся вашим рішенням і спробував інший спосіб.

Будь ласка, спробуйте додати tableView.reloadData()до viewDidAppear().

Це працює для мене.

Я думаю, що все, що стоїть за прокруткою, "те саме", що і reloadData. Коли ви прокручуєте екран, це як дзвонити reloadData()коли viewDidAppear.

Якщо це спрацює, будь ласка, дайте відповідь на цю відповідь, щоб я міг бути впевненим у цьому рішенні.


Я спробую оновити, щоб перевірити, чи створює воно те саме рішення. Дякую!
простота

Вибачте Кан, дивним чином це не вплинуло на макет. Це залишило їх як статичне значення, яке вони встановили як у Interface Builder, а не зменшувало обертаючи їх до належного розміру.
простота

1

На жаль, я не впевнений, чого мені не вистачало. Вищевказані методи не працюють для мене, щоб отримати висоту комірки xib або дозволити layoutifneeded () або UITableView.automaticDimension зробити обчислення висоти. Я шукав і намагався протягом 3 - 4 ночей, але не міг знайти відповіді. Деякі відповіді тут чи на іншому дописі давали мені підказки щодо обхідного шляху. Це дурний метод, але він працює. Просто додайте всі клітинки в масив. А потім встановіть вихід кожного вашого обмеження висоти в раскадровці xib. Нарешті, додайте їх у метод heightForRowAt. Це просто прямо, якщо ви не знайомі з цими API.

Свіфт 4.2

CustomCell.Swift

@IBOutlet weak var textViewOneHeight: NSLayoutConstraint!
@IBOutlet weak var textViewTwoHeight: NSLayoutConstraint!
@IBOutlet weak var textViewThreeHeight: NSLayoutConstraint!

@IBOutlet weak var textViewFourHeight: NSLayoutConstraint!
@IBOutlet weak var textViewFiveHeight: NSLayoutConstraint!

MyTableViewVC.Swift

.
.
var myCustomCells:[CustomCell] = []
.
.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = Bundle.main.loadNibNamed("CustomCell", owner: self, options: nil)?.first as! CustomCell

.
.
myCustomCells.append(cell)
return cell

}


override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

   let totalHeight = myCustomCells[indexPath.row].textViewOneHeight.constant + myCustomCells[indexPath.row].textViewTwoHeight.constant +  myCustomCells[indexPath.row].textViewThreeHeight.constant + myCustomCells[indexPath.row].textViewFourHeight.constant + myCustomCells[indexPath.row].textViewFiveHeight.constant

  return totalHeight + 40 //some magic number


}

1

Я ними користуюся

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    return 100
}

0

Вам слід просто встановити всі обмеження для TOP , BOTTOM і HEIGHT для кожного об’єкта у перегляді / поданнях комірки та видалити існуючу середню позицію Y, якщо є. Тому що там, де ви цього не зробили, накладає артефакти на інші види.


3
Привіт!! Ця відповідь може бути гарною, але краще навести робочий приклад, який пояснює та демонструє вашу відповідь.
ItamarG3

0

Для цілі c це одне з моїх приємних рішень. це спрацювало для мене.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.textLabel.text = [_nameArray objectAtIndex:indexPath.row];
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}

Нам потрібно застосувати ці 2 зміни.

1)cell.textLabel.numberOfLines = 0;
  cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;

2)return UITableViewAutomaticDimension;

0

У мене також була ця проблема спочатку, я вирішив свою проблему з цього коду, намагаючись уникати використання self.tableView.reloadData()замість цього коду для динамічної висоти

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];

0

При використанні статики UITableViewя встановлюю всі значення в UILabels, а потім викликаю tableView.reloadData().


0
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0

І не забудьте додати обмеження для етикетки


0

Свіфт 5 Насолоджуйтесь

tablev.rowHeight = 100
tablev.estimatedRowHeight = UITableView.automaticDimension


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.tablev.dequeueReusableCell(withIdentifier: "ConferenceRoomsCell") as! ConferenceRoomsCell
    cell.lblRoomName.numberOfLines = 0
    cell.lblRoomName.lineBreakMode = .byWordWrapping
    cell.lblRoomName.text = arrNameOfRooms[indexPath.row]
    cell.lblRoomName.sizeToFit()
    return cell
}

-1
self.Itemtableview.estimatedRowHeight = 0;
self.Itemtableview.estimatedSectionHeaderHeight = 0;
self.Itemtableview.estimatedSectionFooterHeight = 0;


[ self.Itemtableview reloadData];
self.Itemtableview.frame = CGRectMake( self.Itemtableview.frame.origin.x,  self.Itemtableview.frame.origin.y,  self.Itemtableview.frame.size.width,self.Itemtableview.contentSize.height + self.Itemtableview.contentInset.bottom + self.Itemtableview.contentInset.top);

Хоча цей код може вирішити питання, включаючи пояснення того, як і чому це вирішує проблему, насправді допомогло б поліпшити якість вашої публікації, і, можливо, призведе до більшої кількості голосів. Пам’ятайте, що ви відповідаєте на запитання читачам у майбутньому, а не лише тому, хто задає зараз. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються.
Сурадж Рао,

-3

Встановіть належне обмеження та оновіть методи делегування як:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

Це вирішить проблему динамічної висоти комірки. ЯКЩО не потрібно перевіряти обмеження.


1
Той самий код, що і відповідь Ахмеда Лотфі на цій самій сторінці ...
Ерік Айя

Хм-м-м, я перевірив
швидкість

1
Ви повинні вказати передбачувану висоту рядків, щоб код працював
Мохсен Шакіба,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.