Как установить высоту ячейки таблицы динамически в зависимости от длины текстовой метки?

Я пытаюсь изучить Obj-C и iOS-программирование, но я все еще очень новый. Я решил попробовать и сделать простое клиентское приложение Reddit. Я пытаюсь отображать сообщения на первой странице в UITableView, причем каждое сообщение представлено его собственной ячейкой.

В ячейке, вот как я устанавливаю заголовок:

cell.textLabel.numberOfLines = 0;
cell.textLabel.text = [[tempDictionary objectForKey:@"data"] objectForKey:@"title"];   
[cell.textLabel sizeToFit];

Тем не менее, ячейка заканчивается, если текст заголовка слишком длинный. Вот изображение:

enter image description here

Как я могу заставить ячейки автоматически настраивать их высоты для размещения более ярких ярлыков заголовков, не пересекая другие ячейки или текстовую метку детали?

Спасибо за помощь!

Ответ 1

Для нового iOS 8 есть новый способ сделать это простым.

Появляется новый параметр, который вычисляет высоту вашей ячейки относительно ограничений автоматического макета. Это UITableViewAutomaticDimension. Вы можете использовать его в методе viewWillAppear вашего контроллера вида.

Цель C:

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  self.tableView.estimatedRowHeight = 70.0; // for example. Set your average height 
  self.tableView.rowHeight = UITableViewAutomaticDimension;
  [self.tableView reloadData];
}

Swift:

override func viewWillAppear(animated: Bool) {
    self.tableView.estimatedRowHeight = 70 // for example. Set your average height 
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.reloadData()

} 

Работайте хорошо и как хотите в своем примере. Что касается меня, я добавляю вещи высоты в viewDidLoad и оставляю в viewWillAppear только reloadData(). Существует также полезный .

Из документации: The default value of rowHeight is UITableViewAutomaticDimension. Я оставляю код таким, какой он есть, на данный момент, но имейте в виду, что вам не нужно устанавливать высоту строки в iOS 8 +.

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

Ответ 2

Вы должны проверить ссылку на документацию для

-[UITableViewDelegate tableView:heightForRowAtIndexPath:]

По существу, вам нужно будет самостоятельно измерить текст, чтобы вернуть правильные размеры для каждой строки таблицы. Если они простые NSStrings, которые, как они выглядят, находятся на вашем скриншоте, вы можете использовать NSString UIKit Additions для их измерения, например

-[NSString sizeWithFont:constrainedToSize:]

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

Если им присваиваются строки, в NSAttributedString UIKit есть аналогичный метод, который называется boundingRectWithSize:options:context:

Ответ 3

Бывает, что мое приложение TidBITS News делает именно то, что вы описываете. И я считаю, что это было одно из первых приложений, чтобы понять, как это сделать; по крайней мере, в то время, когда я это написал, я не знал о других приложениях, которые это сделали. Я опубликовал свой метод в своей книге "Программирование iOS 4", и с тех пор это стало обычным явлением (хотя я не говорю, что все получили его от меня, в основном есть только один разумный способ приблизиться к нему).

Вот объяснение из текущей версии моей книги:

http://www.apeth.com/iOSBook/ch21.html#_variable_row_heights

Как вы можете видеть, трюк заключается в том, чтобы заранее выработать высоты всех строк, вызывая sizeWithFont:constrainedToSize: на ярлыке с данными, которые он будет содержать в каждой строке, и делая необходимую математику. Это связано с тем, что tableView:heightForRowAtIndexPath: будет вызываться вперед, снова и снова, чтобы определить высоты каждой строки, прежде чем вас попросят предоставить данные.

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

Вкл Github У меня также есть загружаемый полный пример проекта, который вы можете прочитать и запустить; он показывает вам, как это сделать с ограничениями (только для iOS 6 и более поздних версий). Ищите пример ch21 с variableHeights в его имени.

Ответ 4

В вашем методе делегата heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath   *)indexPath
{

if (indexPath.row == 2) {
  Message *aMessage = [customTableViewArray objectAtIndex:indexPath.row];

  if ( [aMessage.msgBody length] <= 0 )
    aMessage.msgBody = @"     ";
    CGSize constraint = CGSizeMake(450, 40000.0f);
    CGSize size = [aMessage.msgBody sizeWithFont:[UIFont fontWithName:@"Helvetica" size:14] constrainedToSize:constraint lineBreakMode:UILineBreakModeCharacterWrap];
    size.height = MAX(size.height,36);

    return 136+size.height;

} else if(indexPath.row > 1) {

      Message *aMessage = [customTableViewArray objectAtIndex:indexPath.row];

      if ( [aMessage.msgBody length] <= 0 )
        aMessage.msgBody = @"     ";
        CGSize constraint = CGSizeMake(450, 40000.0f);
        CGSize size = [aMessage.msgBody sizeWithFont:[UIFont fontWithName:@"Helvetica" size:14] constrainedToSize:constraint lineBreakMode:UILineBreakModeCharacterWrap];
        size.height = MAX(size.height,36);

        return 100+size.height;

} else {
      return 146;
   }

}

Прошу прощения, я включил только часть кода. Это все. Поэтому, если сообщение пусто, оно делает его одним размером. Затем в else, если часть инструкции, он получает размер сообщения и основывает размер ячейки на этом размере сообщения.