UITableViewCell com altura UITextView no iOS 7?

Como posso calcular a altura de um UITableViewCell com um UITextView no iOS 7?

Eu encontrei muitas respostas em questões semelhantes, mas sizeWithFont: faz parte de todas as soluções e este método é obsoleto!

Eu sei que tenho que usar - (CGFloat)tableView:heightForRowAtIndexPath: mas como faço para calcular a altura que meu TextView precisa exibir o texto todo?

Em primeiro lugar, é muito importante notar que há uma grande diferença entre o UITextView e o UILabel quando se trata de como o texto é renderizado. O UITextView não só tem inserções em todas as bordas, mas também o layout de texto dentro dele é um pouco diferente.

Portanto, sizeWithFont: é uma maneira ruim de ir para o UITextViews.

Em vez disso, o próprio UITextView tem uma function chamada sizeThatFits: que retornará o menor tamanho necessário para exibir todo o conteúdo do UITextView dentro de uma checkbox delimitadora, que você pode especificar.

Os itens a seguir funcionarão igualmente tanto para o iOS 7 quanto para versões mais antigas e, a partir de agora, não inclui nenhum método que esteja obsoleto.


Solução Simples

 - (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; } 

Esta function terá um NSAttributedString e a largura desejada como um CGFloat e retornará a altura necessária


Solução detalhada

Como fiz recentemente algo semelhante, pensei em compartilhar algumas soluções para os problemas conectados que encontrei. Espero que ajude alguém.

Isso é muito mais profundo e abrangerá o seguinte:

  • Claro: definir a altura de um UITableViewCell base no tamanho necessário para exibir o conteúdo completo de um UITextView contido
  • Responda às alterações de texto (e anime as alterações de altura da linha)
  • Mantendo o cursor dentro da área visível e mantendo o primeiro respondedor no UITextView ao resize o UITableViewCell durante a edição

Se você estiver trabalhando com uma visualização de tabela estática ou se tiver apenas um número conhecido de UITextView , é possível tornar a etapa 2 muito mais simples.

1. Primeiro, sobrescreva o 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. Defina a function que calculou a altura necessária:

Adicione um NSMutableDictionary (neste exemplo chamado textViews ) como uma variável de instância à sua subclass UITableViewController .

Use este dictionary para armazenar referências aos UITextViews individuais da seguinte forma:

(e sim, indexPaths são chaves válidas para dictionarys )

 - (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; } 

Esta function irá agora calcular a altura real:

 - (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. Ativar o redimensionamento durante a edição

Para as próximas duas funções, é importante que o delegado do UITextViews esteja definido como seu UITableViewController . Se você precisar de algo como delegado, você pode contorná-lo fazendo as chamadas relevantes de lá ou usando os ganchos apropriados do 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 (eg through autolayout // constraints), resize it here [self scrollToCursorForTextView:textView]; // OPTIONAL: Follow cursor } 

4. Siga o cursor enquanto Editando

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

Isso fará com que o UITableView role até a posição do cursor, se ele não estiver dentro do Rect visível do 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. Ajuste rect visível, definindo inserções

Durante a edição, partes do seu UITableView podem ser cobertas pelo teclado. Se as inserções de tableviews não forem ajustadas, scrollToCursorForTextView: não poderá rolar para o cursor, se estiver na parte inferior da 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]; } 

E última parte:

Dentro de sua visão carregou, inscreva-se para as notifications para mudanças de teclado através do 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]; } 

Por favor, não fique bravo comigo, por fazer essa resposta tão longa. Embora nem tudo seja necessário para responder à pergunta, acredito que existem outras pessoas com as quais essas questões diretamente relacionadas serão úteis.


ATUALIZAR:

Como Dave Haupert apontou, esqueci de include a function 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); } 

Também notei que scrollToCursorForTextView: ainda incluía uma referência direta a um dos TextFields no meu projeto. Se você tiver um problema com o bodyTextView não sendo encontrado, verifique a versão atualizada da function.

Existe uma nova function para replace sizeWithFont, que é boundingRectWithSize.

Eu adicionei a seguinte function ao meu projeto, que faz uso da nova function no iOS7 e a antiga no iOS menor que 7. Ela tem basicamente a mesma syntax do 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 } } 

Você pode adicionar o IOS_NEWER_OR_EQUAL_TO_7 no seu arquivo prefix.pch em seu projeto como:

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

Se você estiver usando o UITableViewAutomaticDimension, tenho uma solução realmente simples (somente iOS 8). No meu caso, é uma visão de tabela estática, mas eu acho que você poderia adaptar isso para protótipos dynamics …

Eu tenho uma saída de restrição para a altura da exibição de texto e eu implementei os seguintes methods como este:

 // 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]; } 

Mas lembre-se : a textview deve ser rolável e você deve configurar suas restrições de forma que elas trabalhem para a dimensão automática:

  • configurar toda a visão na célula em relação uma à outra, com alturas fixas (incluindo a altura da visão do texto, que você irá alterar programaticamente)
  • a vista mais superior tem o espaçamento superior e a vista mais inferior tem o espaçamento inferior para a superexibição;

O exemplo de célula mais básica é:

  • nenhuma outra vista na célula, exceto a textview
  • 0 margens em torno de todos os lados da textview e uma restrição de altura predefinida para a exibição de texto.

A resposta de Tim Bodeit é ótima. Eu usei o código da Solução Simples para obter corretamente a altura da exibição de texto e usar essa altura em heightForRowAtIndexPath . Mas eu não uso o resto da resposta para resize a exibição de texto. Em vez disso, escrevo código para alterar o frame de exibição de texto em cellForRowAtIndexPath .

Tudo está funcionando no iOS 6 e abaixo, mas no iOS 7 o texto na textview não pode ser totalmente mostrado, embora o frame da exibição de texto seja de fato redimensionado. (Eu não estou usando o Auto Layout ). Deve ser a razão que no iOS 7 há o TextKit e a posição do texto é controlada pelo NSTextContainer no UITextView . Então, no meu caso, preciso adicionar uma linha para definir o someTextView para que ele funcione corretamente no iOS 7.

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

Como a documentação disse, o que essa propriedade faz é:

Controla se o receptor ajusta a altura de seu retângulo delimitador quando sua exibição de texto é redimensionada. Valor padrão: NO.

Se deixá-lo com o valor padrão, depois de resize o frame de someTextView , o tamanho do textContainer não será alterado, levando ao resultado de que o texto só pode ser exibido na área antes de resize.

E talvez seja necessário definir o scrollEnabled = NO , caso haja mais de um textContainer , para que o texto seja textContainer um textContainer para o outro.

Aqui está mais uma solução que visa simplicidade e prototipagem rápida :

Configuração:

  1. Tabela com células protótipo.
  2. Cada célula contém UITextView tamanho dynamic com outros conteúdos.
  3. As células de protótipo estão associadas ao TableCell.h .
  4. UITableView está associado com TableViewController.h .

Solução:

(1) Adicionar ao 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) Adicionar ao 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; } 

Explicação:

Então, o que está acontecendo aqui é: cada exibição de texto está vinculada à altura das células da tabela por restrições verticais e horizontais – isso significa que quando a altura da célula da tabela aumenta, a exibição de texto também aumenta seu tamanho. Eu usei uma versão modificada do código do @manecosta para calcular a altura necessária de uma exibição de texto para ajustar o texto fornecido em uma célula. Então, isso significa que um texto com um número X de caracteres, frameForText: retornará um tamanho que terá uma propriedade size.height que corresponde à altura necessária da textview.

Agora, tudo o que resta é a atualização da altura da célula para corresponder à altura da textview necessária. E isso é conseguido em heightForRowAtIndexPath: Como observado nos comentários, como size.height é apenas a altura da exibição de texto e não da célula inteira, deve haver algum deslocamento adicionado a ela. No caso do exemplo, esse valor era 80.

Uma abordagem se você estiver usando autolayout é deixar o mecanismo de autolayout calcular o tamanho para você. Esta não é a abordagem mais eficiente, mas é bastante conveniente (e indiscutivelmente a mais precisa). Torna-se mais conveniente à medida que aumenta a complexidade do layout da célula – por exemplo, de repente você tem duas ou mais textviews / fields na célula.

Eu respondi uma pergunta semelhante com uma amostra completa para o dimensionamento de células tableview usando o layout automático, aqui:

Como resize o superview para ajustar todas as subvisualizações com o autolayout?

A solução suave completa é a seguinte.

Primeiro, precisamos da class de célula com um textView

 @protocol TextInputTableViewCellDelegate  @optional - (void)textInputTableViewCellTextWillChange:(TextInputTableViewCell *)cell; - (void)textInputTableViewCellTextDidChange:(TextInputTableViewCell *)cell; @end @interface TextInputTableViewCell : UITableViewCell @property (nonatomic, weak) id delegate; @property (nonatomic, readonly) UITextView *textView; @property (nonatomic) NSInteger minLines; @property (nonatomic) CGFloat lastRelativeFrameOriginY; @end #import "TextInputTableViewCell.h" @interface TextInputTableViewCell ()  { 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]; } } 

Em seguida, nós o usamos no TableViewController

 @interface SomeTableViewController ()  @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 
  • Aqui minLines permite definir a altura mínima para o textView (para resistir a minimizar a altura por AutoLayout com UITableViewAutomaticDimension).

  • moveRowAtIndexPath:indexPath: com o mesmo indexPath inicia o cálculo e o novo layout da altura tableViewCell.

  • performWithoutAnimation: remove o efeito colateral (deslocamento de conteúdo tableView pulando ao iniciar uma nova linha durante a digitação).

  • É importante preservar relativeFrameOriginY (não contentOffsetY !) Durante a atualização da célula porque o contentSize das células antes da célula atual pode ser alterado pelo cálculo de autoLayout de maneira inesperada. Ele remove saltos visuais na hifenização do sistema ao digitar palavras longas.

  • Note que você não deve definir a propriedade estimatedRowHeight ! O seguinte não funciona

     self.tableView.estimatedRowHeight = UITableViewAutomaticDimension; 

    Use apenas o método tableViewDelegate.

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

Se não se importa contra a binding fraca entre tableView e tableViewCell e atualizar a geometry do tableView do tableViewCell , é possível atualizar a class TextInputTableViewCell acima:

 @interface TextInputTableViewCell : UITableViewCell @property (nonatomic, weak) id delegate; @property (nonatomic, weak) UITableView *tableView; @property (nonatomic, readonly) UITextView *textView; @property (nonatomic) NSInteger minLines; @end #import "TextInputTableViewCell.h" @interface TextInputTableViewCell ()  { 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 
  1. Coloque a UILabel atrás do seu UITextView.
  2. Use esta resposta: https://stackoverflow.com/a/36054679/6681462 para UILabel que você criou
  3. Dê a eles as mesmas restrições e fonts
  4. Definir o mesmo texto;

A altura da sua célula será calculada pelo conteúdo da UILabel, mas todo o texto será mostrado pelo TextField.

 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; 

Eu acho que desta forma você pode contar a altura da sua visão de texto e, em seguida, resize sua célula tableview de acordo com essa altura para que você possa mostrar o texto completo na célula

Versão rápida

 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 } 

Se você quiser ajustar automaticamente a altura do UITableViewCell base na altura da altura do UITextView interno. Veja minha resposta aqui: https://stackoverflow.com/a/45890087/1245231

A solução é bastante simples e deve funcionar desde o iOS 7. Verifique se a opção Scrolling Enabled está desativada para o UITextView dentro do UITableViewCell no StoryBoard.

Em seguida, no viewDidLoad () de seu UITableViewController, defina tableView.rowHeight = UITableViewAutomaticDimension e tableView.estimatedRowHeight > 0 , como:

 override func viewDidLoad() { super.viewDidLoad() tableView.rowHeight = UITableViewAutomaticDimension tableView.estimatedRowHeight = 44.0 } 

É isso aí. A altura do UITableViewCell será ajustada automaticamente com base na altura do UITextView interno.

Para iOS 8 e acima, você pode simplesmente usar

your_tablview.estimatedrowheight= minheight você quer

 your_tableview.rowheight=UItableviewautomaticDimension 
Intereting Posts