Antes de tudo, é muito importante observar que há uma grande diferença entre o UITextView e o UILabel quando se trata de como o texto é renderizado. O UITextView não apenas possui inserções em todas as bordas, mas também o layout do texto dentro dele é um pouco diferente.
Portanto, sizeWithFont:
é um caminho ruim para o UITextViews.
Em vez disso, UITextView
ele próprio possui uma função chamada sizeThatFits:
que retornará o menor tamanho necessário para exibir todo o conteúdo da UITextView
caixa delimitadora que você pode especificar.
O seguinte funcionará igualmente para as versões iOS 7 e anteriores e, a partir de agora, não inclui nenhum método que foi preterido.
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 função terá ae NSAttributedString
a largura desejada como ae CGFloat
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:
- Obviamente: definir a altura de um com
UITableViewCell
base no tamanho necessário para exibir o conteúdo completo de um contidoUITextView
- Responder a alterações de texto (e animar as alterações de altura da linha)
- Mantendo o cursor dentro da área visível e mantendo o primeiro respondedor
UITextView
ao redimensionar UITableViewCell
enquanto edita
Se você estiver trabalhando com uma exibição de tabela estática ou tiver apenas um número conhecido de UITextView
s, poderá potencialmente tornar a etapa 2 muito mais simples.
1. Primeiro, substitua 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 função que calculou a altura necessária:
Adicione um NSMutableDictionary
(neste exemplo chamado textViews
) como uma variável de instância à sua UITableViewController
subclasse.
Use este dicionário para armazenar referências à pessoa da seguinte UITextViews
maneira:
(e sim, indexPaths são chaves válidas para dicionários )
- (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 função agora calcula 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. Ative o redimensionamento durante a edição
Para as próximas duas funções, é importante que o delegado da UITextViews
seja definido como seu UITableViewController
. Se você precisar de outra coisa como delegado, poderá contorná-lo fazendo as chamadas relevantes a partir daí 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 (e.g. through autolayout
// constraints), resize it here
[self scrollToCursorForTextView:textView]; // OPTIONAL: Follow cursor
}
4. Siga o cursor enquanto edita
- (void)textViewDidBeginEditing:(UITextView *)textView {
[self scrollToCursorForTextView:textView];
}
Isso fará a UITableView
rolagem para a posição do cursor, se 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 o retângulo visível, definindo inserções
Durante a edição, partes do seu UITableView
podem ser cobertas pelo teclado. Se as inserções das visualizações de tablaturas não forem ajustadas, scrollToCursorForTextView:
não será possível rolar para o cursor, se estiver na parte inferior da visualização de tablatura.
- (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 da sua visualização, carregue, inscreva-se nas notificações para alterações do teclado através de 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 por tanto tempo. Embora nem tudo seja necessário para responder à pergunta, acredito que há outras pessoas para quem essas questões diretamente relacionadas serão úteis.
ATUALIZAR:
Como Dave Haupert apontou, eu esqueci de incluir a rectVisible
função:
- (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 isso scrollToCursorForTextView:
ainda incluía uma referência direta a um dos TextFields no meu projeto. Se você tiver um problema em bodyTextView
não ser encontrado, verifique a versão atualizada da função.
attributedText
sem especificar fonte, cor e alinhamento de texto leva à configuração dos valores padrão dos atributos NSAttributedString para o textView. No meu caso, isso causa diferentes alturas da visualização de texto para o mesmo texto.Há uma nova função para substituir sizeWithFont, que é boundingRectWithSize.
Eu adicionei a seguinte função ao meu projeto, que utiliza a nova função no iOS7 e a antiga no iOS menor que 7. Ela tem basicamente a mesma sintaxe que sizeWithFont:
Você pode adicionar esse IOS_NEWER_OR_EQUAL_TO_7 no seu arquivo prefix.pch no seu projeto como:
fonte
Se você estiver usando UITableViewAutomaticDimension, eu tenho uma solução muito simples (somente iOS 8). No meu caso, é uma tabela estática, mas acho que você pode adaptar isso para protótipos dinâmicos ...
Eu tenho uma saída de restrição para a altura da exibição de texto e implementei os seguintes métodos como este:
Mas lembre-se : a visualização do texto deve ser rolável e você deve configurar suas restrições para que funcionem na dimensão automática:
O exemplo mais básico de célula é:
fonte
A resposta de Tim Bodeit é ótima. Usei o código do Simple Solution para obter corretamente a altura da exibição de texto e usá-la
heightForRowAtIndexPath
. Mas não uso o restante da resposta para redimensionar a exibição de texto. Em vez disso, escrevo código para alterar aframe
exibição do textocellForRowAtIndexPath
.Tudo está funcionando no iOS 6 e abaixo, mas no iOS 7 o texto na exibição de texto não pode ser totalmente exibido, mesmo que a
frame
exibição de texto seja redimensionada. (Eu não estou usandoAuto Layout
). Deve ser o motivo pelo qual o iOS 7 existeTextKit
e a posição do texto é controlada porNSTextContainer
inUITextView
. Portanto, no meu caso, preciso adicionar uma linha para definir osomeTextView
fim de fazê-lo funcionar corretamente no iOS 7.Como a documentação disse, o que essa propriedade faz é:
Se deixá-lo com o valor padrão, após redimensionar o
frame
desomeTextView
, o tamanho dotextContainer
não será alterado, levando ao resultado de que o texto só poderá ser exibido na área antes de redimensionar.E talvez seja necessário definir o
scrollEnabled = NO
caso de haver mais de umtextContainer
, para que o texto reflita de umtextContainer
para o outro.fonte
Aqui está mais uma solução que visa a simplicidade e a criação rápida de protótipos :
Configuração:
UITextView
com outros conteúdos.TableCell.h
.UITableView
está associado aTableViewController.h
.Solução:
(1) Adicionar a
TableViewController.m
:(2) Adicionar a
TableCell.m
:Explicação:
Portanto, o que está acontecendo aqui é o seguinte: cada visualização de texto é vinculada à altura das células da tabela por restrições verticais e horizontais - ou seja, quando a altura da célula da tabela aumenta, a visualização do texto também aumenta seu tamanho. Usei uma versão modificada do código de @ manecosta para calcular a altura necessária de uma exibição de texto para ajustar o texto fornecido em uma célula. Isso significa que, dado um texto com o número X de caracteres,
frameForText:
retornará um tamanho que terá uma propriedadesize.height
que corresponda à altura necessária da exibição de texto.Agora, resta apenas atualizar a altura da célula para corresponder à altura da visualização de texto necessária. E isso é alcançado em
heightForRowAtIndexPath:
. Conforme observado nos comentários, comosize.height
existe apenas a altura da exibição do texto e não a célula inteira, deve haver algum deslocamento adicionado a ela. No caso do exemplo, esse valor foi 80.fonte
dream.dream
era o texto que eu estava renderizando na exibição de texto.Uma abordagem, se você estiver usando o pagamento automático, é permitir que o mecanismo do pagamento automático calcule o tamanho para você. Essa não é a abordagem mais eficiente, mas é bastante conveniente (e sem dúvida a mais precisa). Torna-se mais conveniente à medida que a complexidade do layout da célula aumenta - por exemplo, de repente você tem dois ou mais campos de texto / texto na célula.
Respondi a uma pergunta semelhante com uma amostra completa para dimensionar células da tableview usando o layout automático, aqui:
Como redimensionar a superview para caber em todas as subviews com o autolayout?
fonte
A solução completa e suave é a seguinte.
Primeiro, precisamos da classe cell com um textView
Em seguida, usamos no TableViewController
Aqui
minLines
permite definir a altura mínima para o textView (para resistir à minimização da altura pelo AutoLayout com UITableViewAutomaticDimension).moveRowAtIndexPath:indexPath:
com o mesmo indexPath inicia o recálculo e o layout da altura do tableViewCell.performWithoutAnimation:
remove o efeito colateral (deslocamento do conteúdo do tableView pulando ao iniciar uma nova linha enquanto digita).É importante preservar
relativeFrameOriginY
(nãocontentOffsetY
!) Durante a atualização da célula devidocontentSize
às células antes que a célula atual possa ser alterada pelo cálculo do AutoLayout de maneira inesperada. Remove saltos visuais na hifenização do sistema enquanto digita palavras longas.Observe que você não deve definir a propriedade
estimatedRowHeight
! O seguinte não funcionaUse apenas o método tableViewDelegate.
==================================================== ========================
Se alguém não se importa com a ligação fraca entre tableView e tableViewCell e com a atualização da geometria do tableView de tableViewCell , é possível atualizar a
TextInputTableViewCell
classe acima:fonte
A altura da sua célula será calculada pelo conteúdo do UILabel, mas todo o texto será mostrado pelo TextField.
fonte
Eu acho que dessa forma, você pode contar a altura da sua exibição de texto e redimensionar sua célula de tableview de acordo com essa altura, para que você possa mostrar o texto completo na célula
fonte
Versão Swift
fonte
Se você deseja ajustar automaticamente
UITableViewCell
a altura da base, com base na altura da altura internaUITextView
. Veja minha resposta aqui: https://stackoverflow.com/a/45890087/1245231A solução é bastante simples e deve funcionar desde o iOS 7. Verifique se a
Scrolling Enabled
opção está desativada noUITextView
interiorUITableViewCell
do StoryBoard.Em viewDidLoad () do seu UITableViewController, defina o
tableView.rowHeight = UITableViewAutomaticDimension
etableView.estimatedRowHeight > 0
como:É isso aí.
UITableViewCell
A altura da peça será ajustada automaticamente com base naUITextView
altura da parte interna .fonte
Para iOS 8 e superior, você pode simplesmente usar
your_tablview.estimatedrowheight= minheight
você querfonte