Прежде всего, очень важно отметить, что существует большая разница между 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;
}
Эта функция примет a NSAttributedString
и желаемую ширину как a 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
прокрутку перейти к позиции курсора, если он не находится внутри видимого Rect 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:
вы не сможете прокручивать курсор до вашего курсора, если он находится в нижней части tableview.
- (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];
}
Пожалуйста, не сердитесь на меня за такой длинный ответ. Хотя не все это необходимо для ответа на вопрос, я считаю, что есть другие люди, которым эти вопросы, напрямую связанные с этим, будут полезны.
ОБНОВИТЬ:
Как заметил Дэйв Хауперт, я забыл включить 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:
в моем проекте все еще есть прямая ссылка на одно из текстовых полей. Если у вас возникла проблема с тем, что вас bodyTextView
не нашли, проверьте обновленную версию функции.
attributedText
без указания шрифта, цвета и выравнивания текста приводит к установке значений по умолчанию для атрибутов NSAttributedString для textView. В моем случае это приводит к получению разной высоты текстового представления для одного и того же текста.Существует новая функция для замены sizeWithFont, которая является boundingRectWithSize.
Я добавил в свой проект следующую функцию, которая использует новую функцию на iOS7 и старую на iOS ниже 7. Она имеет в основном тот же синтаксис, что и sizeWithFont:
Вы можете добавить этот IOS_NEWER_OR_EQUAL_TO_7 в свой файл prefix.pch в своем проекте как:
источник
Если вы используете UITableViewAutomaticDimension, у меня есть действительно простое (только для iOS 8) решение. В моем случае это статическая таблица, но я думаю, вы могли бы адаптировать ее для динамических прототипов ...
У меня есть выход ограничения для высоты текстового представления, и я реализовал следующие методы, подобные этому:
Но помните : текстовое представление должно быть прокручиваемым, и вы должны настроить свои ограничения так, чтобы они работали для автоматического измерения:
Самый простой пример ячейки:
источник
Ответ Тима Бодейта великолепен. Я использовал код Simple Solution, чтобы правильно получить высоту текстового представления и использовать эту высоту в
heightForRowAtIndexPath
. Но я не использую остальную часть ответа для изменения размера текстового представления. Вместо этого я пишу код, чтобы изменитьframe
текстовое представлениеcellForRowAtIndexPath
.Все работает в iOS 6 и ниже, но в iOS 7 текст в текстовом представлении не может быть полностью отображен, даже если
frame
размер текстового представления действительно изменен. (Не пользуюсьAuto Layout
). Это должно быть причиной того, что в iOS 7 естьTextKit
и положение текста контролируетсяNSTextContainer
inUITextView
. Поэтому в моем случае мне нужно добавить строку для установкиsomeTextView
, чтобы она работала правильно в iOS 7.Как сказано в документации, это свойство делает следующее:
Если оставить его значение по умолчанию, после того, как изменить размер
frame
изsomeTextView
, размерtextContainer
не изменяется, что приводит к тому , что текст может отображаться только в области перед изменением размеров.И, возможно, необходимо установить,
scrollEnabled = NO
если их больше одногоtextContainer
, чтобы текст перекомпоновывался с одногоtextContainer
на другой.источник
Вот еще одно решение, направленное на простоту и быстрое прототипирование :
Настроить:
UITextView
с другим содержимым.TableCell.h
.UITableView
связан сTableViewController.h
.Решение:
(1) Добавить в
TableViewController.m
:(2) Добавить в
TableCell.m
:Объяснение:
Итак, что здесь происходит: каждое текстовое представление привязано к высоте ячеек таблицы вертикальными и горизонтальными ограничениями - это означает, что, когда высота ячейки таблицы увеличивается, текстовое представление также увеличивает свой размер. Я использовал модифицированную версию кода @manecosta, чтобы вычислить необходимую высоту текстового представления, чтобы она соответствовала заданному тексту в ячейке. Это означает, что для текста с числом символов X
frameForText:
будет возвращен размер, который будет иметь свойствоsize.height
, соответствующее требуемой высоте текстового представления.Теперь все, что осталось, - это обновить высоту ячейки, чтобы она соответствовала требуемой высоте текстового представления. И это достигается при
heightForRowAtIndexPath:
. Как отмечено в комментариях, посколькуsize.height
это только высота для текстового представления, а не для всей ячейки, к нему должно быть добавлено некоторое смещение. В случае примера это значение было 80.источник
dream.dream
был текст, который я отображал в текстовом представлении.Один из подходов, если вы используете автоматическое размещение, - позволить механизму автоматического размещения вычислить размер за вас. Это не самый эффективный подход, но он довольно удобный (и, возможно, самый точный). Это становится более удобным по мере роста сложности макета ячейки - например, внезапно у вас есть два или более текстовых представления / поля в ячейке.
Я ответил на аналогичный вопрос с полным образцом для определения размера ячеек tableview с использованием автоматического макета, здесь:
Как изменить размер супервизора, чтобы он соответствовал всем подпредставлениям с автоматическим раскладкой?
источник
Полное гладкое решение выглядит следующим образом.
Во-первых, нам нужен класс ячейки с textView
Далее мы используем его в TableViewController
Здесь
minLines
позволяет установить минимальную высоту для textView (чтобы противостоять минимизации высоты с помощью AutoLayout с помощью UITableViewAutomaticDimension).moveRowAtIndexPath:indexPath:
с тем же indexPath запускает пересчет высоты tableViewCell и перекомпоновку.performWithoutAnimation:
удаляет побочный эффект (смещение содержимого tableView прыгает при начале новой строки при вводе).Важно сохранить
relativeFrameOriginY
(а неcontentOffsetY
!) Во время обновления ячеек, потомуcontentSize
что ячейки до того, как текущая ячейка может быть изменена с помощью вычисления autoLayout неожиданным образом. Он устраняет визуальные скачки при расстановке переносов в системе при наборе длинных слов.Обратите внимание, что вы не должны устанавливать свойство
estimatedRowHeight
! Следующее не работаетИспользуйте только метод tableViewDelegate.
================================================== ========================
Если вы не против слабой привязки между tableView и tableViewCell и обновления геометрии tableView из tableViewCell , можно обновить
TextInputTableViewCell
класс выше:источник
Высота вашей ячейки будет рассчитываться по содержимому UILabel, но весь текст будет отображаться с помощью TextField.
источник
Я думаю, что таким образом вы можете подсчитать высоту своего текстового представления, а затем изменить размер ячейки табличного представления в соответствии с этой высотой, чтобы вы могли отображать полный текст в ячейке
источник
Свифт версия
источник
Если вы хотите автоматически регулировать
UITableViewCell
высоту в зависимости от высоты внутреннейUITextView
высоты. См. Мой ответ здесь: https://stackoverflow.com/a/45890087/1245231Решение довольно простое и должно работать, начиная с iOS 7. Убедитесь, что этот
Scrolling Enabled
параметр отключен дляUITextView
внутренней частиUITableViewCell
в StoryBoard.Затем в вашем UITableViewController viewDidLoad () установите
tableView.rowHeight = UITableViewAutomaticDimension
и,tableView.estimatedRowHeight > 0
например:Вот и все.
UITableViewCell
Высота будет автоматически отрегулирована в зависимости от внутреннейUITextView
высоты.источник
Для iOS 8 и выше вы можете просто использовать
your_tablview.estimatedrowheight= minheight
вы хотитеисточник