UITableViewCell с высотой UITextView в iOS 7?

Как я могу вычислить высоту UITableViewCell с UITextView в ней в iOS 7?

Я нашел много ответов на подобные вопросы, но sizeWithFont: участвует в каждом решении, и этот метод устарел!

Я знаю, что мне нужно использовать - (CGFloat)tableView:heightForRowAtIndexPath:, но как я могу рассчитать высоту моего TextView, чтобы отобразить весь текст?

Ответ 1

Прежде всего, очень важно отметить, что существует большая разница между UITextView и UILabel, когда дело доходит до того, как текст визуализируется. Не только UITextView имеет вставки на всех границах, но и макет текста внутри него немного отличается.

Следовательно, sizeWithFont: - плохой путь для UITextViews.

Вместо этого UITextView имеет функцию sizeThatFits:, которая вернет наименьший размер, необходимый для отображения всего содержимого UITextView внутри ограничивающего прямоугольника, который вы можете указать.

Следующее будет одинаково работать как для iOS 7, так и для более старых версий, и в настоящее время не содержит никаких методов, которые устарели.


Простое решение

- (CGFloat)textViewHeightForAttributedText: (NSAttributedString*)text andWidth: (CGFloat)width {
    UITextView *calculationView = [[UITextView alloc] init];
    [calculationView setAttributedText:text];
    CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

Эта функция примет NSAttributedString и желаемую ширину как CGFloat и вернет требуемую высоту


Подробное решение

Поскольку я недавно сделал что-то подобное, я подумал, что также поделился некоторыми решениями связанных проблем, с которыми я столкнулся. Надеюсь, это поможет кому-то.

Это более подробно и будет охватывать следующее:

  • Конечно: установка высоты UITableViewCell на основе размера, необходимого для отображения полного содержимого содержащегося UITextView
  • Отвечайте на изменения текста (анимируйте изменения высоты строки)
  • Сохранение курсора внутри видимой области и сохранение первого ответчика в UITextView при изменении размера UITableViewCell при редактировании

Если вы работаете со статическим представлением таблицы или у вас есть только известное число UITextView s, вы можете сделать шаг 2 намного проще.

1. Во-первых, перезапишите heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    // check here, if it is one of the cells, that needs to be resized
    // to the size of the contained UITextView
    if (  )             
        return [self textViewHeightForRowAtIndexPath:indexPath];
    else
    // return your normal height here:
            return 100.0;           
}

2. Определите функцию, которая рассчитала необходимую высоту:

Добавьте NSMutableDictionary (в этом примере под названием textViews) в качестве переменной экземпляра в ваш подкласс UITableViewController.

Используйте этот словарь для хранения ссылок на отдельный UITextViews следующим образом:

(и да, indexPaths являются действительными ключами для словарей)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Do you cell configuring ...

    [textViews setObject:cell.textView forKey:indexPath];
    [cell.textView setDelegate: self]; // Needed for step 3

    return cell;
}

Эта функция теперь рассчитает фактическую высоту:

- (CGFloat)textViewHeightForRowAtIndexPath: (NSIndexPath*)indexPath {
    UITextView *calculationView = [textViews objectForKey: indexPath];
    CGFloat textViewWidth = calculationView.frame.size.width;
    if (!calculationView.attributedText) {
        // This will be needed on load, when the text view is not inited yet

        calculationView = [[UITextView alloc] init];
        calculationView.attributedText = // get the text from your datasource add attributes and insert here
        textViewWidth = 290.0; // Insert the width of your UITextViews or include calculations to set it accordingly
    }
    CGSize size = [calculationView sizeThatFits:CGSizeMake(textViewWidth, FLT_MAX)];
    return size.height;
}

3. Включить изменение размера при редактировании

Для следующих двух функций важно, чтобы делегат из UITextViews был установлен на ваш UITableViewController. Если вам нужно что-то еще в качестве делегата, вы можете обойти его, выполнив соответствующие вызовы или используя соответствующие крючки NSNotificationCenter.

- (void)textViewDidChange:(UITextView *)textView {

    [self.tableView beginUpdates]; // This will cause an animated update of
    [self.tableView endUpdates];   // the height of your UITableViewCell

    // If the UITextView is not automatically resized (e.g. through autolayout 
    // constraints), resize it here

    [self scrollToCursorForTextView:textView]; // OPTIONAL: Follow cursor
}

4. Следуйте курсору при редактировании

- (void)textViewDidBeginEditing:(UITextView *)textView {
    [self scrollToCursorForTextView:textView];
}

Это приведет к тому, что UITableView выделит позицию курсора, если она не находится внутри видимого прямоугольника UITableView:

- (void)scrollToCursorForTextView: (UITextView*)textView {

    CGRect cursorRect = [textView caretRectForPosition:textView.selectedTextRange.start];

    cursorRect = [self.tableView convertRect:cursorRect fromView:textView];

    if (![self rectVisible:cursorRect]) {
        cursorRect.size.height += 8; // To add some space underneath the cursor
        [self.tableView scrollRectToVisible:cursorRect animated:YES];
    }
}

5. Отрегулируйте видимый прямоугольник, установив вставки

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

- (void)keyboardWillShow:(NSNotification*)aNotification {
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, kbSize.height, 0.0);
    self.tableView.contentInset = contentInsets;
    self.tableView.scrollIndicatorInsets = contentInsets;
}

- (void)keyboardWillHide:(NSNotification*)aNotification {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.35];
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, 0.0, 0.0);
    self.tableView.contentInset = contentInsets;
    self.tableView.scrollIndicatorInsets = contentInsets;
    [UIView commitAnimations];
}

И последняя часть:

Внутри вашего вида загрузилась регистрация для уведомлений о изменениях клавиатуры с помощью NSNotificationCenter:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

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


UPDATE:

Как отметил Дэйв Хауперт, я забыл включить функцию rectVisible:

- (BOOL)rectVisible: (CGRect)rect {
    CGRect visibleRect;
    visibleRect.origin = self.tableView.contentOffset;
    visibleRect.origin.y += self.tableView.contentInset.top;
    visibleRect.size = self.tableView.bounds.size;
    visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;

    return CGRectContainsRect(visibleRect, rect);
}

Также я заметил, что scrollToCursorForTextView: по-прежнему включал прямую ссылку на один из TextField в моем проекте. Если у вас возникла проблема с bodyTextView не найденным, проверьте обновленную версию функции.

Ответ 2

Существует новая функция для замены sizeWithFont, которая является ограничивающейRectWithSize.

Я добавил в проект следующую функцию, которая использует новую функцию на iOS7 и старую на iOS ниже 7. Она имеет в основном тот же синтаксис, что и sizeWithFont:

    -(CGSize)text:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size{
        if(IOS_NEWER_OR_EQUAL_TO_7){
            NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                              font, NSFontAttributeName,
                                              nil];

            CGRect frame = [text boundingRectWithSize:size
                                              options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                           attributes:attributesDictionary
                                              context:nil];

            return frame.size;
        }else{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            return [text sizeWithFont:font constrainedToSize:size];
#pragma clang diagnostic pop
        }
    }

Вы можете добавить, что IOS_NEWER_OR_EQUAL_TO_7 в файле prefix.pch в вашем проекте:

#define IOS_NEWER_OR_EQUAL_TO_7 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] >= 7.0 )

Ответ 3

Если вы используете UITableViewAutomaticDimension, у меня действительно простое решение (только для iOS 8). В моем случае это статический вид таблицы, но я думаю, вы могли бы адаптировать его для динамических прототипов...

У меня есть выход ограничения для высоты текстового вида, и я применил следующие методы:

// Outlets

@property (weak, nonatomic) IBOutlet UITextView *textView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewHeight;


// Implementation

#pragma mark - Private Methods

- (void)updateTextViewHeight {
    self.textViewHeight.constant = self.textView.contentSize.height + self.textView.contentInset.top + self.textView.contentInset.bottom;
}

#pragma mark - View Controller Overrides

- (void)viewDidLoad {
    [super viewDidLoad];
    [self updateTextViewHeight];
}

#pragma mark - TableView Delegate & Datasource

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 80;
}

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

#pragma mark - TextViewDelegate

- (void)textViewDidChange:(UITextView *)textView {
    [self.tableView beginUpdates];
    [self updateTextViewHeight];
    [self.tableView endUpdates];
}

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

  • настроить все представления в ячейке по отношению друг к другу с фиксированными высотами (включая высоту текстового вида, которую вы будете изменять программно)
  • верхний вид сверху имеет верхний интервал, а нижний вид имеет нижнее расстояние до супер-представления;

Самый простой пример ячейки:

  • нет других представлений в ячейке, кроме textview
  • 0 поля вокруг всех сторон текстового вида и предопределенное ограничение высоты для текстового представления.

Ответ 4

Тим Бодеит ответ велик. Я использовал код Simple Solution, чтобы правильно получить высоту текстового представления и использовать эту высоту в heightForRowAtIndexPath. Но я не использую оставшуюся часть ответа, чтобы изменить размер текстового представления. Вместо этого я пишу код для изменения frame текстового представления в cellForRowAtIndexPath.

Все работает в iOS 6 и ниже, но в iOS 7 текст в текстовом представлении не может быть полностью показан, даже если текстовое представление frame действительно изменено. (Я не использую Auto Layout). Это должно быть причиной того, что в iOS 7 есть TextKit, а позиция текста контролируется NSTextContainer в UITextView. Поэтому в моем случае мне нужно добавить строку для установки someTextView, чтобы она работала корректно в iOS 7.

    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        someTextView.textContainer.heightTracksTextView = YES;
    }

Как сказано в документации, что это свойство делает:

Управляет тем, регулирует ли приемник высоту его ограничивающего прямоугольник, когда изменяется его текстовое представление. Значение по умолчанию: NO.

Если оставить значение по умолчанию, после изменения размера frame в someTextView размер textContainer не будет изменен, что приведет к тому, что текст будет отображаться только в области перед изменением размера.

И, возможно, необходимо установить scrollEnabled = NO в случае, если имеется более одного textContainer, так что текст будет переходить от одного textContainer к другому.

Ответ 5

Вот еще одно решение, нацеленное на простоту и быстрое прототипирование:

Настройка:

  • Таблица с ячейками прототипа.
  • Каждая ячейка содержит динамический размер UITextView w/другое содержимое.
  • Ячейки прототипа связаны с TableCell.h.
  • UITableView связан с TableViewController.h.

Решение:

(1) Добавить в TableViewController.m:

 // This is the method that determines the height of each cell.  
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    // I am using a helper method here to get the text at a given cell.
    NSString *text = [self getTextAtIndex:indexPath];

    // Getting the height needed by the dynamic text view.
    CGSize size = [self frameForText:text sizeWithFont:nil constrainedToSize:CGSizeMake(300.f, CGFLOAT_MAX)];

    // Return the size of the current row.
    // 80 is the minimum height! Update accordingly - or else, cells are going to be too thin.
    return size.height + 80; 
}

// Think of this as some utility function that given text, calculates how much 
// space would be needed to fit that text.
- (CGSize)frameForText:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
{
    NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                          font, NSFontAttributeName,
                                          nil];
    CGRect frame = [text boundingRectWithSize:size
                                      options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                   attributes:attributesDictionary
                                      context:nil];

    // This contains both height and width, but we really care about height.
    return frame.size;
}

// Think of this as a source for the text to be rendered in the text view. 
// I used a dictionary to map indexPath to some dynamically fetched text.
- (NSString *) getTextAtIndex: (NSIndexPath *) indexPath
{
    return @"This is stubbed text - update it to return the text of the text view.";
}

(2) Добавить в TableCell.m:

// This method will be called when the cell is initialized from the storyboard
// prototype. 
- (void)awakeFromNib
{
    // Assuming TextView here is the text view in the cell. 
    TextView.scrollEnabled = YES;
}

Объяснение:

Итак, что происходит здесь: каждый текстовый вид привязан к высоте ячеек таблицы по вертикальным и горизонтальным ограничениям - это означает, что когда высота ячейки таблицы увеличивается, текстовое представление также увеличивает его размер. Я использовал модифицированную версию кода @manecosta для вычисления требуемой высоты текстового представления, чтобы он соответствовал заданному тексту в ячейке. Таким образом, это означает, что для текста с X количеством символов frameForText: возвращает размер, который будет иметь свойство size.height, которое соответствует требуемой высоте текста.

Теперь остается только обновить высоту ячейки, соответствующую требуемой высоте отображения текста. И это достигается при heightForRowAtIndexPath:. Как отмечено в комментариях, поскольку size.height - это только высота текстового представления, а не всей ячейки, должно быть добавлено некоторое смещение. В случае примера это значение было 80.

Ответ 6

Один подход, если вы используете автозапуск, должен позволить автозапуску вычислить размер для вас. Это не самый эффективный подход, но он довольно удобен (и, возможно, самый точный). Это становится более удобным, так как возрастает сложность компоновки ячеек. внезапно у вас есть два или несколько текстовых полей/полей в ячейке.

Я ответил на аналогичный вопрос с полным образцом для определения размеров табличных ячеек с использованием автоматического макета, здесь:

Как изменить размер супервизора для соответствия всем подзонам с автозапуском?

Ответ 7

Полное гладкое решение выглядит следующим образом.

Сначала нам нужен класс ячейки с textView

@protocol TextInputTableViewCellDelegate <NSObject>
@optional
- (void)textInputTableViewCellTextWillChange:(TextInputTableViewCell *)cell;
- (void)textInputTableViewCellTextDidChange:(TextInputTableViewCell *)cell;
@end

@interface TextInputTableViewCell : UITableViewCell
@property (nonatomic, weak) id<TextInputTableViewCellDelegate> delegate;
@property (nonatomic, readonly) UITextView *textView;
@property (nonatomic) NSInteger minLines;
@property (nonatomic) CGFloat lastRelativeFrameOriginY;
@end


#import "TextInputTableViewCell.h"

@interface TextInputTableViewCell () <UITextViewDelegate> {
    NSLayoutConstraint *_heightConstraint;
}
@property (nonatomic) UITextView *textView;
@end

@implementation TextInputTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.selectionStyle = UITableViewCellSelectionStyleNone;

        _textView = [UITextView new];
        _textView.translatesAutoresizingMaskIntoConstraints = NO;
        _textView.delegate = self;
        _textView.scrollEnabled = NO;
        _textView.font = CELL_REG_FONT;
        _textView.textContainer.lineFragmentPadding = 0.0;
        _textView.textContainerInset = UIEdgeInsetsZero;
        [self.contentView addSubview:_textView];

        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];
        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];

        _heightConstraint = [NSLayoutConstraint constraintWithItem: _textView
                         attribute: NSLayoutAttributeHeight
                         relatedBy: NSLayoutRelationGreaterThanOrEqual
                         toItem: nil
                         attribute: NSLayoutAttributeNotAnAttribute
                         multiplier: 0.0
                         constant: (_textView.font.lineHeight + 15)];
        _heightConstraint.priority = UILayoutPriorityRequired - 1;
        [_textView addConstraint:_heightConstraint];
    }
    return self;
}

- (void)prepareForReuse {
    [super prepareForReuse];    
    self.minLines = 1;
}

- (void)setMinLines:(NSInteger)minLines {
    _heightConstraint.constant = minLines * _textView.font.lineHeight + 15;
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if ([self.delegate respondsToSelector:@selector(textInputTableViewCellTextWillChange:)]) {
        [self.delegate textInputTableViewCellTextWillChange:self];
    }
    return YES;
}

- (void)textViewDidChange:(UITextView *)textView {
    if ([self.delegate respondsToSelector:@selector(textInputTableViewCellTextDidChange:)]) {
        [self.delegate textInputTableViewCellTextDidChange:self];
    }
}

Затем мы используем его в TableViewController

@interface SomeTableViewController () <TextInputTableViewCellDelegate>
@end

@implementation SomeTableViewController

. . . . . . . . . . . . . . . . . . . .

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    TextInputTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: TextInputTableViewCellIdentifier forIndexPath:indexPath];
    cell.delegate = self;
    cell.minLines = 3;
    . . . . . . . . . .  
    return cell;
}

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

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

- (void)textInputTableViewCellWillChange:(TextInputTableViewCell *)cell {
    cell.lastRelativeFrameOriginY = cell.frame.origin.y - self.tableView.contentOffset.y;
}

- (void)textInputTableViewCellTextDidChange:(TextInputTableViewCell *)cell {
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

    [UIView performWithoutAnimation:^{
        [self.tableView moveRowAtIndexPath:indexPath toIndexPath:indexPath];
    }];

    CGFloat contentOffsetY = cell.frame.origin.y - cell.lastRelativeFrameOriginY;
    self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, contentOffsetY);

    CGRect caretRect = [cell.textView caretRectForPosition:cell.textView.selectedTextRange.start];
    caretRect = [self.tableView convertRect:caretRect fromView:cell.textView];

    CGRect visibleRect = self.tableView.bounds;
    visibleRect.origin.y += self.tableView.contentInset.top;
    visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;
    BOOL res = CGRectContainsRect(visibleRect, caretRect);
    if (!res) {
        caretRect.size.height += 5;
        [self.tableView scrollRectToVisible:caretRect animated:NO];
    }
}
@end
  • Здесь minLines позволяет установить минимальную высоту для textView (для автоматически уменьшать высоту с помощью AutoLayout с помощью UITableViewAutomaticDimension).

  • moveRowAtIndexPath:indexPath: с тем же самым запуском indexPath tableViewCell перерасчет высоты и повторная компоновка.

  • performWithoutAnimation: удаляет побочный эффект (содержимое tableView смещение при запуске новой строки при вводе текста).

  • Важно сохранить relativeFrameOriginY (не contentOffsetY!) во время обновления ячейки, поскольку contentSize ячейки до того, как текущая ячейка может быть изменена путем исчисления autoLayout неожиданным образом. Он удаляет визуальные скачки при переносе системы при вводе длинных слов.

  • Обратите внимание, что вы не должны устанавливать свойство estimatedRowHeight! следующий не работает

    self.tableView.estimatedRowHeight = UITableViewAutomaticDimension;
    

    Использовать только метод tableViewDelegate.

=============================================== ===========================

Если вы не возражаете против слабого связывания между tableView и tableViewCell и обновляете геометрию таблицыView из tableViewCell, можно обновить класс TextInputTableViewCell выше:

@interface TextInputTableViewCell : UITableViewCell
@property (nonatomic, weak) id<TextInputTableViewCellDelegate> delegate;
@property (nonatomic, weak) UITableView *tableView;
@property (nonatomic, readonly) UITextView *textView;
@property (nonatomic) NSInteger minLines;
@end


#import "TextInputTableViewCell.h"

@interface TextInputTableViewCell () <UITextViewDelegate> {
    NSLayoutConstraint *_heightConstraint;
    CGFloat _lastRelativeFrameOriginY;
}
@property (nonatomic) UITextView *textView;
@end

@implementation TextInputTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.selectionStyle = UITableViewCellSelectionStyleNone;

        _textView = [UITextView new];
        _textView.translatesAutoresizingMaskIntoConstraints = NO;
        _textView.delegate = self;
        _textView.scrollEnabled = NO;
        _textView.font = CELL_REG_FONT;
        _textView.textContainer.lineFragmentPadding = 0.0;
        _textView.textContainerInset = UIEdgeInsetsZero;
        [self.contentView addSubview:_textView];

        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];
        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];

        _heightConstraint = [NSLayoutConstraint constraintWithItem: _textView
                         attribute: NSLayoutAttributeHeight
                         relatedBy: NSLayoutRelationGreaterThanOrEqual
                         toItem: nil
                         attribute: NSLayoutAttributeNotAnAttribute
                         multiplier: 0.0
                         constant: (_textView.font.lineHeight + 15)];
        _heightConstraint.priority = UILayoutPriorityRequired - 1;
        [_textView addConstraint:_heightConstraint];
    }
    return self;
}

- (void)prepareForReuse {
    [super prepareForReuse];    
    self.minLines = 1;
    self.tableView = nil;
}

- (void)setMinLines:(NSInteger)minLines {
    _heightConstraint.constant = minLines * _textView.font.lineHeight + 15;
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {

    _lastRelativeFrameOriginY = self.frame.origin.y - self.tableView.contentOffset.y;
    return YES;
}

- (void)textViewDidChange:(UITextView *)textView {

    NSIndexPath *indexPath = [self.tableView indexPathForCell:self];
    if (indexPath == nil) return;

    [UIView performWithoutAnimation:^{
        [self.tableView moveRowAtIndexPath:indexPath toIndexPath:indexPath];
    }];

    CGFloat contentOffsetY = self.frame.origin.y - _lastRelativeFrameOriginY;
    self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, contentOffsetY);

    CGRect caretRect = [self.textView caretRectForPosition:self.textView.selectedTextRange.start];
    caretRect = [self.tableView convertRect:caretRect fromView:self.textView];

    CGRect visibleRect = self.tableView.bounds;
    visibleRect.origin.y += self.tableView.contentInset.top;
    visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;

    BOOL res = CGRectContainsRect(visibleRect, caretRect);
    if (!res) {
        caretRect.size.height += 5;
        [self.tableView scrollRectToVisible:caretRect animated:NO];
    }
}
@end

Ответ 8

  • Поместите UILabel за свой UITextView.
  • Используйте этот ответ: fooobar.com/questions/23315/... для созданного вами UILabel
  • Дайте им те же ограничения и шрифты
  • Установите их одинаковый текст;

Высота вашей ячейки будет вычисляться по содержимому UILabel, но весь текст будет отображаться с помощью TextField.

Ответ 9

UITextView *txtDescLandscape=[[UITextView alloc] initWithFrame:CGRectMake(2,20,310,2)];

    txtDescLandscape.editable =NO;
    txtDescLandscape.textAlignment =UITextAlignmentLeft;
    [txtDescLandscape setFont:[UIFont fontWithName:@"ArialMT" size:15]];
    txtDescLandscape.text =[objImage valueForKey:@"imgdescription"];
    txtDescLandscape.text =[txtDescLandscape.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    [txtDescLandscape sizeToFit];
    [headerView addSubview:txtDescLandscape];

    CGRect txtViewlandscpframe = txtDescLandscape.frame;
    txtViewlandscpframe.size.height = txtDescLandscape.contentSize.height;
    txtDescLandscape.frame = txtViewlandscpframe;

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

Ответ 10

Быстрая версия

func textViewHeightForAttributedText(text: NSAttributedString, andWidth width: CGFloat) -> CGFloat {
    let calculationView = UITextView()
    calculationView.attributedText = text
    let size = calculationView.sizeThatFits(CGSize(width: width, height: CGFloat.max))
    return size.height
}

Ответ 11

Если вы хотите автоматически настроить высоту UITableViewCell в зависимости от высоты внутренней высоты UITextView. См. Мой ответ здесь: fooobar.com/questions/23314/...

Решение довольно простое и должно работать с iOS 7. Убедитесь, что параметр Scrolling Enabled отключен выключен для UITextView внутри UITableViewCell в StoryBoard.

Затем в вашем UITableViewController viewDidLoad() установите tableView.rowHeight = UITableViewAutomaticDimension и tableView.estimatedRowHeight > 0, например:

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 44.0
}

Что это. Высота UITableViewCell будет автоматически отрегулирована на основе внутренней высоты UITextView.

Ответ 12

Для iOS 8 и выше вы можете просто использовать

your_tablview.estimatedrowheight= minheight вы хотите

your_tableview.rowheight=UItableviewautomaticDimension