Como dimensionar um UITextView para o seu conteúdo?

521

Existe uma boa maneira de ajustar o tamanho de UITextViewa de acordo com seu conteúdo? Digamos, por exemplo, eu tenho um UITextViewque contém uma linha de texto:

"Hello world"

Depois, adiciono outra linha de texto:

"Goodbye world"

Existe uma boa maneira no Cocoa Touch de obter o rectque reterá todas as linhas na exibição de texto para que eu possa ajustar a exibição principal adequadamente?

Como outro exemplo, observe o campo das notas para eventos no aplicativo Calendário - observe como a célula (e UITextViewela contém) se expande para conter todas as linhas de texto na sequência das notas.

drewh
fonte
considere atualizar a resposta correta, uma vez que a aceita leva a cálculos desnecessários, agora existe uma propriedade contentSize para esse problema.
Juan Boero

Respostas:

610

Isso funciona para iOS 6.1 e iOS 7:

- (void)textViewDidChange:(UITextView *)textView
{
    CGFloat fixedWidth = textView.frame.size.width;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = textView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    textView.frame = newFrame;
}

Ou no Swift (funciona com o Swift 4.1 no iOS 11)

let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)

Se você deseja suporte para o iOS 6.1, também deve:

textview.scrollEnabled = NO;
jhibberd
fonte
1
Testado no iOS 7 para redimensionar um UITextView em um UITableViewCell. Funciona muito bem. Esta é a única resposta que finalmente funcionou para mim. Obrigado!
31413 Alex
37
Eu precisava de textview.scrollEnabled = NO;impedir que o texto de ficar cortado até mesmo no iOS 7.
Brian
19
Eu recomendo usar CGFLOAT_MAXmacro em vez de MAXFLOAT. Adequado em ambas as plataformas de 32/64 bits.
Eonil
3
Aquele que enfrenta pouca flutuação antes de entrar na próxima linha adiciona este `NSRange bottom = NSMakeRange (textView.text.length -1, 1); [textView scrollRangeToVisible: bottom]; `
ajay_nasa 28/08
4
Por que existem duas chamadas separadas para sizeThatFits (...) na versão Swift? Qual é a primeira linha?
Nekonari 5/05
576

Isso não funciona mais no iOS 7 ou superior

Na verdade, existe uma maneira muito fácil de redimensionar a UITextViewaltura correta do conteúdo. Isso pode ser feito usando o UITextView contentSize.

CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

Uma coisa a notar é que o correto contentSizesó está disponível depois de o UITextViewter sido adicionada à vista com addSubview. Antes disso, é igual aframe.size

Isso não funcionará se o layout automático estiver ativado. Com o layout automático, a abordagem geral é usar o sizeThatFitsmétodo e atualizar o constantvalor em uma restrição de altura.

CGSize sizeThatShouldFitTheContent = [_textView sizeThatFits:_textView.frame.size];
heightConstraint.constant = sizeThatShouldFitTheContent.height;

heightConstraint é uma restrição de layout que você normalmente configura por meio de um IBOutlet vinculando a propriedade à restrição de altura criada em um storyboard.


Apenas para adicionar a esta resposta incrível, 2014, se você:

[self.textView sizeToFit];

há uma diferença de comportamento apenas no iPhone6 ​​+ :

insira a descrição da imagem aqui

Com apenas o 6+ (não os 5s ou 6), ele adiciona "mais uma linha em branco" ao UITextView. A "solução RL" corrige isso perfeitamente:

CGRect _f = self.mainPostText.frame;
_f.size.height = self.mainPostText.contentSize.height;
self.mainPostText.frame = _f;

Corrige o problema da "linha extra" em 6 ou mais.

Ronnie Liew
fonte
2
Você salvou o meu dia. Eu estava lutando com a extensão da função de classe selfCalculating esquecendo disso. Obrigado.
Lukasz
4
Aha! Eu estava definindo a altura da exibição de texto e, em seguida, ajustando a altura da exibição que continha. Aparentemente, quando fiz isso, a altura da visualização do texto estava sendo ajustada. Definir a altura da vista que contém primeiro faz com que as coisas funcionem conforme o esperado (ou, melhor, esperado).
Hot Licks
11
O uso de [_textView sizeToFit] atualiza a propriedade contentSize, removendo o requisito de adicioná-lo ao scrollView antecipadamente.
22411 Rodrigo
1
Se estiver usando o layout automático, ligue layoutIfNeededpara a superview. Então você pode pegar a altura de contentSize.
Phatmann # 21/13
4
É sobre o redimensionamento do contêiner externo. Esse comportamento mudou no iOS 7. Mostro na pergunta vinculada onde adicionar sizeToFit e layoutIfNeeded.
Henrik Erlandsson
93

Para fazer um dimensionamento dinâmico UITextViewdentro de a UITableViewCell, achei a seguinte combinação funcionando no Xcode 6 com o iOS 8 SDK:

  • Adicione a UITextViewa UITableViewCelle restrinja-o para os lados
  • Defina o UITextView's scrollEnabledpropriedade para NO. Com a rolagem ativada, o quadro da UITextViewé independente do tamanho do conteúdo, mas com a rolagem desativada, há um relacionamento entre as duas.
  • Se sua tabela estiver usando a altura da linha padrão original de 44, ela calculará automaticamente a altura da linha, mas se você alterou a altura da linha padrão para outra coisa, talvez seja necessário ativar manualmente o cálculo automático da altura da linha em viewDidLoad:

    tableView.estimatedRowHeight = 150;
    tableView.rowHeight = UITableViewAutomaticDimension;

Para dimensionamentos dinâmicos somente leitura UITextView, é isso. Se você estiver permitindo que os usuários editem o texto no seu UITextView, também precisará:

  • Implemente o textViewDidChange:método do UITextViewDelegateprotocolo e diga tableViewpara repintar a si próprio toda vez que o texto for editado:

    - (void)textViewDidChange:(UITextView *)textView;
    {
        [tableView beginUpdates];
        [tableView endUpdates];
    }
  • E não esqueça de colocar o UITextViewdelegado em algum lugar, dentro Storyboardou foratableView:cellForRowAtIndexPath:

Brett Donald
fonte
Melhor resposta para mim. Funcionou perfeitamente e o UITableViewAutomaticDimension foi adicionado no iOS 5, por isso é compatível com versões anteriores.
smmelzer
4
Não funcionou muito bem para mim. O método textViewDidChange faz com que minha tableview salte toda vez que digito um caractere. O que eu sugiro é que, em vez de usar esse método, no método tableView: cellForRowAtIndexPath, para a linha com o textview, se você estiver em um modo somente leitura definido .scrollEnabled como NO e se estiver em um conjunto de modos de exibição de edição rolagem ativada para SIM. Dessa forma, ao exibi-lo, sempre mostrará o texto completo e, ao editá-lo, começará com o texto completo e, à medida que você adiciona mais texto, permanecerá do mesmo tamanho com o texto anterior rolando para cima
SimonTheDiver
3
além disso, adicionei uma restrição> = height à visualização de texto, pois um campo de texto vazio não tinha altura e não podia ser tocado para iniciar a edição.
SimonTheDiver
Excelente solução. Para mim, o tableView.rowHeight = UITableViewAutomaticDimensionfoi desnecessário.
Christopher Pickslay
Mais uma vez obrigado Brett Donald! Esqueci como fazer isso e encontrei sua resposta mais de 1 ano depois 😀.
Eric Conner
76

Solução de trabalho muito fácil, usando código e storyboard.

Por Código

textView.scrollEnabled = false

Por Storyboard

Desmarque a opção Ativar rolagem

insira a descrição da imagem aqui

Não há necessidade de fazer nada além disso.

Alok
fonte
5
Esta resposta está correta. No StoryBoard, você tem o TextView AutoSize exatamente como um UILabel. Tudo o que precisamos fazer é definir scrollEnabled = false.
Pnavk
4
Essencialmente, isso está correto: se você estiver usando restrições de Autolayout e desligar a rolagem, tudo funcionará.
Dan Rosenstark
2
Muito obrigado. Era tão simples, apenas desative a rolagem no storyboard ou código, que será como UILabel com linhas 0.
samir105
@Mansuu .... Esta não é uma solução garantida, pois existem coisas que você pode fazer para substituir o tamanho do conteúdo intrínseco e, se você alterar o texto após a exibição da visualização, ele não será atualizado, a menos que você defina isso. para cima também. Mas, essas coisas permanecem verdadeiras para definir numberOfLines = 0 em um campo de texto também. Se isso não funcionar, você provavelmente terá outras restrições que definirão implicitamente uma altura.
Jake T.
2
@iOS se você estiver adicionando uma restrição de altura, diminua a prioridade das restrições, caso contrário não funcionará.
Alok
61

Rápido :

textView.sizeToFit()
Juan Boero
fonte
14
Além disso, descobri que precisava definir a rolagem ativada como falsa para que isso funcionasse. textView.scrollEnabled = false
tmarkiewicz
1
Você deve se lembrar de chamar textView.layoutIfNeeded () depois textView.sizeToFit ()
Daniel Kuta
5
@tmarkiewicz Funciona quando o texto cabe na tela do seu dispositivo, mas será um problema quando o texto for maior que o espaço existente na tela. Você não poderá rolar para ver o restante do texto.
Francisco Romero
Esta é a resposta !!! Não há necessidade de soluções mais complicadas !!! @FranciscoRomero Por que não colocar o textview em uma célula a célula tabela ou exibição colleciton então você pode sempre rolar a mesa ou colleciton view ....
Ben Smith
23

Na minha experiência (limitada),

- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode

não respeita os caracteres de nova linha, portanto, você pode acabar com muito menos do CGSizeque o necessário.

- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

parece respeitar as novas linhas.

Além disso, o texto não é renderizado na parte superior do UITextView. No meu código, defino a nova altura de UITextView24 pixels maior que a altura retornada pelos sizeOfFontmétodos.

user63934
fonte
3
Isso obtém o tamanho como se fosse desenhar o texto em um UILabel. Se você definir esse tamanho para o quadro do uitextview, ainda terá algumas rolagens necessárias.
Kevlar
22

No iOS6, você pode verificar a contentSizepropriedade do UITextView logo após definir o texto. No iOS7, isso não funcionará mais. Se você deseja restaurar esse comportamento para iOS7, coloque o seguinte código em uma subclasse de UITextView.

- (void)setText:(NSString *)text
{
    [super setText:text];

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        CGRect rect = [self.textContainer.layoutManager usedRectForTextContainer:self.textContainer];
        UIEdgeInsets inset = self.textContainerInset;
        self.contentSize = UIEdgeInsetsInsetRect(rect, inset).size;
    }
}
phatmann
fonte
2
Onde posso ler mais sobre isso? Estou totalmente perdido quanto ao aparentemente novo comportamento do iOS 7 em relação a isso.
Stian Høiland
Qual o significado do tamanho variável do CGSize?
Tchelow
Eu removi o tamanho, não deveria estar lá.
Phatmann
18

Vou postar a solução certa na parte inferior da página, caso alguém seja corajoso (ou desesperado o suficiente) para ler até este ponto.

Aqui está o repositório do gitHub para aqueles que não querem ler todo esse texto: resizableTextView

Isso funciona com o iOs7 (e acredito que funcionará com o iOs8) e com a execução automática. Você não precisa de números mágicos, desative o layout e coisas assim. Solução curta e elegante.

Eu acho que todo código relacionado a restrições deve ir para o updateConstraintsmétodo Então, vamos fazer o nosso ResizableTextView.

O primeiro problema que encontramos aqui é que não sabemos o tamanho real do conteúdo antes do viewDidLoadmétodo. Podemos pegar uma estrada longa e de buggy e calculá-la com base no tamanho da fonte, quebras de linha, etc. Mas precisamos de uma solução robusta, então faremos:

CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];

Portanto, agora sabemos o real contentSize, não importa onde estamos: antes ou depois viewDidLoad. Agora adicione restrição de altura no textView (via storyboard ou código, não importa como). Ajustaremos esse valor com nosso contentSize.height:

[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
    if (constraint.firstAttribute == NSLayoutAttributeHeight) {
        constraint.constant = contentSize.height;
        *stop = YES;
    }
}];

A última coisa a fazer é dizer à superclasse updateConstraints.

[super updateConstraints];

Agora nossa classe se parece com:

ResizableTextView.m

- (void) updateConstraints {
    CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];

    [self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
        if (constraint.firstAttribute == NSLayoutAttributeHeight) {
            constraint.constant = contentSize.height;
            *stop = YES;
        }
    }];

    [super updateConstraints];
}

Bonito e limpo, certo? E você não precisa lidar com esse código em seus controladores !

Mas espere! S NÃO ANIMAÇÃO!

Você pode animar facilmente as alterações para fazer textViewalongamentos sem problemas. Aqui está um exemplo:

    [self.view layoutIfNeeded];
    // do your own text change here.
    self.infoTextView.text = [NSString stringWithFormat:@"%@, %@", self.infoTextView.text, self.infoTextView.text];
    [self.infoTextView setNeedsUpdateConstraints];
    [self.infoTextView updateConstraintsIfNeeded];
    [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];
Nikita Took
fonte
4
Use CGFLOAT_MAX, não FLT_MAX.
Rob mayoff
Eu gostaria de poder dar a você mais de um voto positivo nesta solução incrível!
Scooter
13

Você tentou [textView sizeThatFits:textView.bounds]?

Edit: sizeThatFits retorna o tamanho, mas na verdade não redimensiona o componente. Não tenho certeza se é isso que você quer ou se [textView sizeToFit]é mais o que você estava procurando. Em ambos os casos, não sei se ele se encaixará perfeitamente no conteúdo como você deseja, mas é a primeira coisa a tentar.

Mike McMaster
fonte
2
sizetofit salva o dia
michaelsnowden
9

Outro método é encontrar o tamanho que uma determinada string ocupará usando o NSStringmétodo:

-(CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

Isso retorna o tamanho do retângulo que se ajusta à sequência especificada com a fonte especificada. Passe em um tamanho com a largura desejada e a altura máxima e, em seguida, observe a altura retornada para caber no texto. Existe uma versão que permite especificar também o modo de quebra de linha.

Você pode usar o tamanho retornado para alterar o tamanho da sua visualização.

Code Addict
fonte
8

Se você não tiver o UITextViewprático (por exemplo, você está dimensionando as células da visualização da tabela), terá que calcular o tamanho medindo a string e, em seguida, contabilizando os 8 pt de preenchimento em cada lado de a UITextView. Por exemplo, se você conhece a largura desejada da sua exibição de texto e deseja descobrir a altura correspondente:

NSString * string = ...;
CGFloat textViewWidth = ...;
UIFont * font = ...;

CGSize size = CGSizeMake(textViewWidth - 8 - 8, 100000);
size.height = [string sizeWithFont:font constrainedToSize:size].height + 8 + 8;

Aqui, cada 8 representa uma das quatro arestas acolchoadas e 100000 serve apenas como um tamanho máximo muito grande.

Na prática, você pode adicionar um extra font.leadingà altura; isso adiciona uma linha em branco abaixo do texto, que pode parecer melhor se houver controles visualmente pesados ​​diretamente abaixo da exibição de texto.

Brent Royal-Gordon
fonte
resultado perfeito no iOS 8.1
Logic
Estofamento era a chave para mim
thibaut noah
8

Podemos fazer isso por restrições.

  1. Defina restrições de altura para o UITextView. insira a descrição da imagem aqui

2.Crie o IBOutlet para essa restrição de altura.

 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *txtheightconstraints;

3. não se esqueça de definir o delegado para sua visualização de texto.

4)

-(void)textViewDidChange:(UITextView *)textView
{
    CGFloat fixedWidth = textView.frame.size.width;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = textView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    NSLog(@"this is updating height%@",NSStringFromCGSize(newFrame.size));
    [UIView animateWithDuration:0.2 animations:^{
                  _txtheightconstraints.constant=newFrame.size.height;
    }];

}

atualize sua restrição assim :)

Kishore Kumar
fonte
esse é um apelido FANTÁSTICO!
Gordo
Definir a constante precisa ser seguido por [textView layoutIfNeeded]; no bloco de animação. (Animações autoLayout fazê-lo assim.)
Will Larche
7

As seguintes coisas são suficientes:

  1. Lembre-se de definir a rolagem ativada como NÃO para o seu UITextView:

insira a descrição da imagem aqui

  1. Defina corretamente as restrições de layout automático.

Você pode até usar UITableViewAutomaticDimension.

Bartłomiej Semańczyk
fonte
6

Combinado com a resposta de Mike McMaster, você pode fazer algo como:

[myTextView setDelegate: self];

...

- (void)textViewDidChange:(UITextView *)textView {
  if (myTextView == textView) {
     // it changed.  Do resizing here.
  }
}
Olie
fonte
6

Eu descobri uma maneira de redimensionar a altura de um campo de texto de acordo com o texto dentro dele e também organizar um rótulo abaixo dele com base na altura do campo de texto! Aqui está o código.

UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300, 10)];
NSString *str = @"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different.";
_textView.text = str;

[self.view addSubview:_textView];
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 5 + frame.origin.y + frame.size.height, 300, 20)];
lbl.text = @"Hello!";
[self.view addSubview:lbl];
dheeraj
fonte
Aqui, a coordenada '5' em y do UILabel é o espaço que eu quero entre o textView e o Label.
dheeraj
6

Pessoas que usam o autolayout e seu tamanho não estão funcionando. Verifique sua restrição de largura uma vez. Se você perdeu a restrição de largura, a altura será precisa.

Não há necessidade de usar nenhuma outra API. apenas uma linha resolveria todo o problema.

[_textView sizeToFit];

Aqui, eu estava preocupado apenas com a altura, mantendo a largura fixa e perdendo a restrição de largura do meu TextView no storyboard.

E isso foi para mostrar o conteúdo dinâmico dos serviços.

Espero que isso possa ajudar ..

Swaroop S
fonte
6

A partir do iOS 8, é possível usar os recursos de layout automático de um UITableView para redimensionar automaticamente um UITextView sem nenhum código personalizado. Eu coloquei um projeto no github que demonstra isso em ação, mas aqui está a chave:

  1. O UITextView deve ter a rolagem desativada, o que você pode fazer programaticamente ou por meio do construtor de interface. Não será redimensionado se a rolagem estiver ativada porque a rolagem permite exibir o conteúdo maior.
  2. Em viewDidLoad para o UITableViewController, você deve definir um valor para estimativaRowHeight e, em seguida, definir rowHeightcomo UITableViewAutomaticDimension.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.estimatedRowHeight = self.tableView.rowHeight;
    self.tableView.rowHeight = UITableViewAutomaticDimension;
}
  1. O destino de implantação do projeto deve ser iOS 8 ou superior.
Chuck Krutsinger
fonte
1
Esse tipo de resposta é desencorajado. Você deve postar o código relevante aqui.
Antzi
5

Revisei todas as respostas e todas estão mantendo a largura fixa e ajustando apenas a altura. Se você deseja ajustar também a largura, pode facilmente usar este método:

portanto, ao configurar sua exibição de texto, defina a rolagem desativada

textView.isScrollEnabled = false

e, em seguida, no método delegado, func textViewDidChange(_ textView: UITextView)adicione este código:

func textViewDidChange(_ textView: UITextView) {
    let newSize = textView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
    textView.frame = CGRect(origin: textView.frame.origin, size: newSize)
}

Saídas:

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Peter Stajger
fonte
método delegado não está sendo chamado @ Peter Stajger
Mansuu ...
4

Isso funcionou muito bem quando eu precisei transformar o texto em uma UITextViewárea específica:

// O texto já deve ser adicionado à subvisão, ou contentviewsize estará errado.

- (nulo) reduzaFontToFit: (UITextView *) tv {
    UIFont * font = tv.font;
    double pointSize = font.pointSize;

    while (tv.contentSize.height> tv.frame.size.height && pointSize> 7.0) {
        pointSize - = 1.0;
        UIFont * newFont = [UIFont fontWithName: font.fontName tamanho: pointSize];
        tv.font = newFont;
    }
    if (pointSize! = font.pointSize)
        NSLog (@ "fonte até% .1f de% .1f", pointSize, tv.font.pointSize);
}
Bill Cheswick
fonte
4

aqui está a versão rápida do @jhibberd

    let cell:MsgTableViewCell! = self.tableView.dequeueReusableCellWithIdentifier("MsgTableViewCell", forIndexPath: indexPath) as? MsgTableViewCell
    cell.msgText.text = self.items[indexPath.row]
    var fixedWidth:CGFloat = cell.msgText.frame.size.width
    var size:CGSize = CGSize(width: fixedWidth,height: CGFloat.max)
    var newSize:CGSize = cell.msgText.sizeThatFits(size)
    var newFrame:CGRect = cell.msgText.frame;
    newFrame.size = CGSizeMake(CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), newSize.height);
    cell.msgText.frame = newFrame
    cell.msgText.frame.size = newSize        
    return cell
Alnamrouti com tarifa
fonte
6
A questão é realmente independente da linguagem. É realmente necessário voltar e escrever portas rápidas para todas as respostas sobre questões relacionadas ao UIKit? Parece que isso cria uma conversa barulhenta.
precisa saber é o seguinte
o problema que a maioria destas questões não tem nenhuma linguagem de programação específica para que você vai encontrá-lo no Google, mesmo se você procurar linguagem rápida
Fareed Alnamrouti
4

desativar rolagem

adicionar constaints

e adicione seu texto

[yourTextView setText:@"your text"];
[yourTextView layoutIfNeeded];

se você usar UIScrollView, adicione-o também;

[yourScrollView layoutIfNeeded];

-(void)viewDidAppear:(BOOL)animated{
    CGRect contentRect = CGRectZero;

    for (UIView *view in self.yourScrollView.subviews) {
         contentRect = CGRectUnion(contentRect, view.frame);
    }
    self.yourScrollView.contentSize = contentRect.size;
}
alicanozkara
fonte
3

Para o iOS 7.0, em vez de definir frame.size.heighto uso contentSize.height(que atualmente não faz nada) [textView sizeToFit].

Veja esta pergunta .

Stian Høiland
fonte
2

Usar o UITextViewDelegate é a maneira mais fácil:

func textViewDidChange(_ textView: UITextView) {
    textView.sizeToFit()
    textviewHeight.constant = textView.contentSize.height
}
f0go
fonte
1

Espero que isto ajude:

- (void)textViewDidChange:(UITextView *)textView {
  CGSize textSize = textview.contentSize;
  if (textSize != textView.frame.size)
      textView.frame.size = textSize;
}
Dr. Marty
fonte
Isso não funciona! Isso causa um erro: "lvalue necessário como operando esquerdo da atribuição"
leviathan
Você só pode atribuir a textView.frame.
jweyrich
1

se algum outro chegar aqui, esta solução funcionará para mim, 1 "Ronnie Liew" +4 "user63934" (meu texto chega do serviço da web): observe os 1000 (nada pode ser tão grande "no meu caso")

UIFont *fontNormal = [UIFont fontWithName:FONTNAME size:FONTSIZE];

NSString *dealDescription = [client objectForKey:@"description"];

//4
CGSize textSize = [dealDescription sizeWithFont:fontNormal constrainedToSize:CGSizeMake(containerUIView.frame.size.width, 1000)];

CGRect dealDescRect = CGRectMake(10, 300, containerUIView.frame.size.width, textSize.height);

UITextView *dealDesc = [[[UITextView alloc] initWithFrame:dealDescRect] autorelease];

dealDesc.text = dealDescription;
//add the subview to the container
[containerUIView addSubview:dealDesc];

//1) after adding the view
CGRect frame = dealDesc.frame;
frame.size.height = dealDesc.contentSize.height;
dealDesc.frame = frame;

E isso é ... Saúde

Alejo JM
fonte
1

A melhor maneira que descobri para redimensionar a altura do UITextView de acordo com o tamanho do texto.

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
                       constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX)];

ou você pode usar

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
                       constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX) lineBreakMode:NSLineBreakByTruncatingTail];
Manju
fonte
1

Para aqueles que desejam que a visualização de texto realmente suba e mantenha a posição final

CGRect frame = textView.frame;
frame.size.height = textView.contentSize.height;

if(frame.size.height > textView.frame.size.height){
    CGFloat diff = frame.size.height - textView.frame.size.height;
    textView.frame = CGRectMake(0, textView.frame.origin.y - diff, textView.frame.size.width, frame.size.height);
}
else if(frame.size.height < textView.frame.size.height){
    CGFloat diff = textView.frame.size.height - frame.size.height;
    textView.frame = CGRectMake(0, textView.frame.origin.y + diff, textView.frame.size.width, frame.size.height);
}
Gal Blank
fonte
1

O único código que funcionará é o que usa 'SizeToFit', como na resposta jhibberd acima, mas na verdade ele não será capturado, a menos que você o chame no ViewDidAppear ou ligue-o ao evento alterado de texto UITextView.

Mohammad Zekrallah
fonte
1

Com base na resposta de Nikita Took, cheguei à seguinte solução no Swift, que funciona no iOS 8 com autolayout:

    descriptionTxt.scrollEnabled = false
    descriptionTxt.text = yourText

    var contentSize = descriptionTxt.sizeThatFits(CGSizeMake(descriptionTxt.frame.size.width, CGFloat.max))
    for c in descriptionTxt.constraints() {
        if c.isKindOfClass(NSLayoutConstraint) {
            var constraint = c as! NSLayoutConstraint
            if constraint.firstAttribute == NSLayoutAttribute.Height {
                constraint.constant = contentSize.height
                break
            }
        }
    }
Apfelsaft
fonte
1

Resposta rápida: O código a seguir calcula a altura do seu textView.

                let maximumLabelSize = CGSize(width: Double(textView.frame.size.width-100.0), height: DBL_MAX)
                let options = NSStringDrawingOptions.TruncatesLastVisibleLine | NSStringDrawingOptions.UsesLineFragmentOrigin
                let attribute = [NSFontAttributeName: textView.font!]
                let str = NSString(string: message)
                let labelBounds = str.boundingRectWithSize(maximumLabelSize,
                    options: NSStringDrawingOptions.UsesLineFragmentOrigin,
                    attributes: attribute,
                    context: nil)
                let myTextHeight = CGFloat(ceilf(Float(labelBounds.height)))

Agora você pode definir a altura do seu textView como myTextHeight

RawMean
fonte
Desculpe, o que significa: let attribute = [NSFontAttributeName: textView.text.font!] este é realmente o código Swift sem erros?) Você quis dizer # let attribute = [NSFontAttributeName: textView.font!]
Massmaker