UITableViewCell с высотой UITextView в iOS 7?
Как я могу вычислить высоту UITableViewCell с UITextView в нем в iOS 7?
Я нашел много ответов на подобные вопросы, но sizeWithFont:
принимает участие в каждом решении, и этот метод устарел!
Я знаю, что должен использовать - (CGFloat)tableView:heightForRowAtIndexPath:
но как мне вычислить высоту, которая нужна моему TextView для отображения всего текста?
12 ответов
Прежде всего, очень важно отметить, что существует большая разница между 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
Прокрутите до положения курсора, если он не находится внутри видимого 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
может быть покрыто клавиатурой. Если таблицы не вставлены, 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];
}
Пожалуйста, не сердитесь на меня за такой длинный ответ. Хотя не все это необходимо для ответа на этот вопрос, я считаю, что есть другие люди, которым эти вопросы, связанные непосредственно, будут полезны.
ОБНОВИТЬ:
Как отметил Дейв Хауперт, я забыл включить 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:
все еще включал прямую ссылку на одно из TextFields в моем проекте. Если у вас есть проблемы с bodyTextView
не найден, проверьте обновленную версию функции.
Есть новая функция для замены sizeWithFont, которая является boundingRectWithSize.
Я добавил в свой проект следующую функцию, которая использует новую функцию на 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 )
Если вы используете 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 полей вокруг всех сторон текстового представления и предопределенного ограничения высоты для текстового представления.
Ответ Тима Бодейта великолепен. Я использовал код 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;
}
Как сказано в документации, то, что делает это свойство:
Определяет, регулирует ли получатель высоту ограничивающего прямоугольника при изменении размера текстового представления. Значение по умолчанию: НЕТ.
Если оставить значение по умолчанию, после изменения размера frame
из someTextView
Размер textContainer
не изменяется, что приводит к тому, что текст может отображаться только в области перед изменением размера.
И, возможно, это необходимо, чтобы установить scrollEnabled = NO
в случае, если есть более одного textContainer
, так что текст будет перекомпонован с одного textContainer
к другому.
Вот еще одно решение, которое направлено на простоту и быстрое создание прототипов:
Настроить:
- Стол с прототипом ячеек.
- Каждая ячейка содержит динамический размер
UITextView
с другим содержанием. - Клетки-прототипы связаны с
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.
Один из подходов, если вы используете autolayout, - это позволить подсистеме autolayout рассчитать размер для вас. Это не самый эффективный подход, но он довольно удобный (и, возможно, самый точный). Это становится более удобным по мере роста сложности макета ячейки - например, внезапно у вас появляется два или более текстовых представлений / поля в ячейке.
Я ответил на аналогичный вопрос с полным примером для определения размера ячеек таблицы с помощью автоматического макета, здесь:
Как изменить суперпредставление, чтобы оно соответствовало всем подпредставлениям с autolayout?
- Поместите UILabel позади вашего UITextView.
- Используйте этот ответ: /questions/33354383/dinamicheski-uvelichivat-vyisotu-uilabel-and-tableview-cell/33354389#33354389 для UILabel вы создали
- Дайте им те же ограничения и шрифты
- Установите для них один и тот же текст;
Высота вашей ячейки будет рассчитываться по содержанию UILabel, но весь текст будет отображаться TextField.
Полное гладкое решение состоит в следующем.
Во-первых, нам нужен класс ячейки с 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 и обновления геометрии tableView из 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
Если вы хотите автоматически настроить UITableViewCell
высота в зависимости от высоты внутреннего UITextView
высота Смотрите мой ответ здесь: /questions/19951961/uitableviewcell-uitextview-s-dinamicheskoj-vyisotoj/19951983#19951983
Решение довольно простое и должно работать с iOS 7. Убедитесь, что Scrolling Enabled
опция отключена для UITextView
внутри UITableViewCell
в раскадровке.
Затем в viewDidLoad () вашего UITableViewController установите tableView.rowHeight = UITableViewAutomaticDimension
а также tableView.estimatedRowHeight > 0
такие как:
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44.0
}
Вот и все. UITableViewCell
высота будет автоматически отрегулирована на основе внутренней UITextView
высота
Swift версия
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
}
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;
я думаю, что таким образом вы можете посчитать высоту вашего текстового представления, а затем изменить размер ячейки таблицы в соответствии с этой высотой, чтобы вы могли отображать полный текст в ячейке
Для iOS 8 и выше вы можете просто использовать
your_tablview.estimatedrowheight= minheight
ты хочешь
your_tableview.rowheight=UItableviewautomaticDimension