it-swarm.com.ru

Проблема динамической высоты для ячеек UITableView (Swift)

Динамический текст переменной длины вводится в метки ячеек таблицы. Для того чтобы высоты ячеек таблицы были динамически измерены, я реализовал в viewDidLoad():

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

Это хорошо работает для ячеек, к которым еще предстоит прокрутить (как UITableViewAutomaticDimention вызывается при прокрутке к ячейке), но не для ячеек, которые изначально отображаются на экране при загрузке таблицы с данными.

Я попытался просто перезагрузить данные (как это предлагается во многих других ресурсах):

self.tableView.reloadData()

и в viewDidAppear(), и в viewWillAppear(), и это было безрезультатно. Я заблудился .. Кто-нибудь знает, как заставить XCode визуализировать динамическую высоту для ячеек, загруженных изначально на экране? 

Пожалуйста, дайте мне знать, если есть лучший альтернативный метод.

48
simplexity

Попробуй это:

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

ПРАВКА

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

Swift 4

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

Swift 4.2

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

Определите выше оба метода.
Это решает проблему.

PS: для этого необходимы ограничения сверху и снизу.

Вот пример

88
iDhaval

Использовать этот:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300

и не используйте: heightForRowAtIndexPath делегировать функцию

Кроме того, на доске объявлений не устанавливайте высоту надписи, которая содержит большое количество данных. Дайте ему top, bottom, leading, trailing ограничения. 

29
ami rt

Свифт 3

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160

И !!! В storyBoard: Вы ДОЛЖНЫ установить ограничения TOP & BOTTOM для своей метки . Ничего другого.

12
Vladimir Vozniak

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

Все, что я сделал, это сделал размер метки по умолчанию больше, чем потенциально мог бы быть контент, и отразил его в высоте estimatedRowHeight. Ранее я устанавливал высоту строки по умолчанию в Интерфейсном Разработчике на 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 или Интерфейсном Разработчике, но она работает как шарм. Попробуйте!

10
simplexity

Установите автоматический размер для высоты строки и предполагаемой высоты строки и выполните следующие шаги:

@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 (& режим разрыва строки = обрезать хвост)
  • Установите все ограничения (сверху, снизу, справа налево) относительно его контейнера superview/cell.
  • Необязательно : Установите минимальную высоту для метки, если вы хотите, чтобы минимальная вертикальная область была покрыта меткой, даже если нет данных.

Вот образец метки с динамическими ограничениями по высоте.

enter image description here

7
Krunal

Для динамического определения размера ячейки UITableView потребовалось 2 вещи 

  1. Установка правильного ограничения вашего представления внутри ячейки табличного представления (в основном это включает в себя предоставление вашему представлению правильных ограничений top, bottom и traling)
  2. Вызов этих свойств TableView в viewDidLoad ()

     tableView.rowHeight = UITableViewAutomaticDimension
    
     tableView.estimatedRowHeight = 140
    

Это замечательный учебник по самооб измерению (ячейки динамического табличного представления), написанный на Swift 3.

7
osama

Для Swift 3 вы можете использовать следующее:

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

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

Пытаться

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

У меня была такая же проблема, и она работает для меня.

2
Maickell Vilela

Для автоматического изменения размера UITableViewCell убедитесь, что вы делаете эти изменения:

  • В раскадровке ваш UITableView должен содержать только динамические прототипные ячейки (он не должен использовать статические ячейки ), Иначе автоматическое изменение размера не будет работать. 
  • В раскадровке. UILableel вашего UITableViewCell настроен на все 4 ограничения: верхнее, нижнее, Ведущее и конечное ограничения.
  • В Storyboard количество строк вашего UITableViewCell UILabel должно быть 0
  • В функции ViewDidLoad вашего UIViewController установлено под UITableView Свойства:

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

Я был просто вдохновлен вашим решением и попробовал другой способ.

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

Это работает для меня.

Я думаю, что за прокруткой стоит то же самое, что и у reloadData. Когда вы прокручиваете экран, это похоже на вызов reloadData() когда viewDidAppear.

Если это работает, пожалуйста, ответьте на этот ответ, чтобы я мог быть уверен в этом решении.

1
Kang Cheng

Для 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
}

Здесь вам нужно добавить верхний, нижний, правый и левый ограничения

1
iOS

Я пользуюсь этим

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

    return 100
}
1
gms

К сожалению, я не уверен, чего мне не хватало. Вышеприведенные методы не работают для меня, чтобы получить высоту ячейки XIB или позволить layoutifneeded () или UITableView.automaticDimension сделать вычисление высоты. Я искал и пробовал от 3 до 4 ночей, но не смог найти ответ. Некоторые ответы здесь или в другом посте дали мне подсказки для обходного пути, хотя. Это глупый метод, но он работает. Просто добавьте все свои клетки в массив. А затем установите выход каждого из ваших ограничений по высоте в раскадровке xib. Наконец, добавьте их в метод heightForRowAt. Это просто, если вы не знакомы с этими API.

Swift 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
William Tong

В дополнение к тому, что сказали другие, 

УСТАНАВЛИВАЙТЕ ОГРАНИЧЕНИЯ ВАШЕЙ ЭТИКЕТКИ ОТНОСИТЕЛЬНО НАДЗОРОВ

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

Затем убедитесь, что высота вашей метки установлена ​​больше или равна 0, а количество строк установлено на 0. 

Затем в ViewDidLoad добавьте:

tableView.estimatedRowHeight = 695

tableView.rowHeight = UITableViewAutomaticDimension

0
Will Said

Для 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
}

Удачного кодирования :)

0
Ariven Nadar

Для Objective 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
iOS

Я также получил эту проблему изначально, я решил свою проблему из этого кода Попробуйте избежать использования self.tableView.reloadData() вместо этого кода для динамической высоты

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

Вы должны просто установить все ограничения дляTOP,BOTTOMиHEIGHTдля каждого объекта в представлении/просмотре ячейки и удалить существующее среднее Y положение, если есть , Потому что там, где вы этого не сделали, ставятся артефакты на другие взгляды.

0
Gennady Dmitrik