Pull to refresh

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

Reading time 3 min
Views 10K
Всем доброго времени суток, недавно столкнулся с такой проблемой, что при записи текста (длинного текста) в ячейку таблицы, её Label не увеличивается пропорционально объёму текста, то есть если там 3 слова, то все хорошо, но если записать туда 3-4 предложения, то появится примерно вот такая штука.



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

После того, как вы создали NavigationController, сделали свой ViewController наследником от UITableViewController'а, нам надо создать класс для нашей кастомной ячейки. Создаем новый класс называем его например customCell и указываем, что он наследник класса UITableViewCell.

#import "customCell.h"

@implementation customCell

- (void)awakeFromNib {
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

В файле *.m сразу создадутся 2 метода, которые в нашем случае нам не понадобятся.

Далее помещаем в наш прототип ячейки UILabel. Кликаем на него мышкой и устанавливаем такие настройки, важно, чтобы вот эти параметры были именно такими.



Lines = 0 говорит о том, что ячейка может иметь неограниченное количество строк, а Line Break = Word Wrap, что слова будут переноситься на новую строку, когда закончится место в этой. Но это еще не все, теперь нам надо связать наш UILabel с файлом customCell.h

После этого вернемся в файл ViewController и воспользуемся делегатом heightForRowAtIndexPath.

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

Можно проводить калькуляцию в этом делегате прямо в вашем ViewController'е, но я бы советовал перенести все это в customCell.m для экономии места в основном файле.

Перейдем в customCell.h и создадим метод с плюсиком.

+(CGFloat) heightForText:(NSString*) text;


И вернемся к файлу .m для его реализации.

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

boundingRectWithSize

в него мы записываем длину ячейки, с отступами или без, высоту (если нужно ее ограничить) и «засунуть» вашу Dictionary с атрибутами. Пример кода ниже.

+(CGFloat) heightForText:(NSString*) text {
    
    CGFloat offset = 1.0;
    
    UIFont* font = [UIFont systemFontOfSize:17.f];
    
    NSMutableParagraphStyle* paragraph = [[NSMutableParagraphStyle alloc] init];
    [paragraph setLineBreakMode:NSLineBreakByWordWrapping];    
    
    NSDictionary* attributes =
    [NSDictionary dictionaryWithObjectsAndKeys:
     font , NSFontAttributeName,
     paragraph, NSParagraphStyleAttributeName, nil];
    
    CGRect rect = [text boundingRectWithSize:CGSizeMake(320 - 2 * offset, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil];
    
    return CGRectGetHeight(rect) + 2 * offset;
    
}

Теперь возвращаемся во ViewController и в делегате с помощью return вызвать метод класса cusomCell и получить от него информацию о высоте вашей ячейки.

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    return [customCell heightForText: self.textStringHabr];
    
}

Проверяем.



Всё работает!

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

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 1;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString* identifier = @"cell";
    
    customCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    
    if (!cell) {
        cell = [[customCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    }
    
    cell.testTextLabel.text = self.textStringHabr;
    
    return cell;
}


Для тех, кто пишет на Swift, всё гораздо проще, Apple избавила нас от этого написания кода и там все делается с помощью всего лишь двух строчек кода.

self.tableView.rowHeight = UITableViewAutomaticDimension
        
self.tableView.estimatedRowHeight = 44.0

Информация взята из уроков Алексея Скутаренко.

Спасибо за внимание, надеюсь, что смог помочь хоть чем то.
Tags:
Hubs:
0
Comments 19
Comments Comments 19

Articles