Pergunta

Existe uma boa maneira de ajustar o tamanho de um UITextView conformar-se ao seu conteúdo?Digamos, por exemplo, que eu tenha um UITextView que contém uma linha de texto:

"Hello world"

Em seguida, adiciono outra linha de texto:

"Goodbye world"

Existe uma boa maneira no Cocoa Touch de obter o rect isso manterá todas as linhas na visualização de texto para que eu possa ajustar a visualização principal de acordo?

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

Foi útil?

Solução

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 em Swift (funciona com 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 iOS 6.1, você também deve:

textview.scrollEnabled = NO;

Outras dicas

Isso não funciona mais no iOS 7 ou superior

Na verdade, existe uma maneira muito fácil de redimensionar o UITextView à altura 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 contentSize só está disponível depois o UITextView foi adicionado à visualização com addSubview.Antes disso é igual a frame.size

Isso não funcionará se o layout automático estiver ativado.Com o layout automático, a abordagem geral é usar o sizeThatFits método e atualizar o constant valor 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.


Só para acrescentar a esta resposta incrível, 2014, se você:

[self.textView sizeToFit];

há uma diferença de comportamento com o iPhone6+ apenas:

enter image description here

Somente com 6+ (não 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;

Ele corrige o problema de "linha extra" em 6+.

Para fazer um dimensionamento dinâmico UITextView dentro de um UITableViewCell, descobri que a seguinte combinação funciona no Xcode 6 com o SDK do iOS 8:

  • Adicione um UITextView para um UITableViewCell e restringi-lo aos lados
  • Colocou o UITextViewde scrollEnabled propriedade para NO.Com a rolagem habilitada, o quadro do UITextView é independente do tamanho do conteúdo, mas com a rolagem desativada, existe uma relação entre os dois.
  • Se sua tabela estiver usando a altura de linha padrão original de 44, ela calculará automaticamente as alturas das linhas, mas se você alterou a altura da linha padrão para outra coisa, pode ser necessário ativar manualmente o cálculo automático das alturas das linhas em viewDidLoad:

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

Para dimensionamento dinâmico somente leitura UITextViewé isso.Se você estiver permitindo que os usuários editem o texto em seu UITextView, você também precisa:

  • Implementar o textViewDidChange: método do UITextViewDelegate protocolo e diga ao tableView para se repintar toda vez que o texto for editado:

    - (void)textViewDidChange:(UITextView *)textView;
    {
        [tableView beginUpdates];
        [tableView endUpdates];
    }
    
  • E não se esqueça de definir o UITextView delegar em algum lugar, seja em Storyboard ou em tableView:cellForRowAtIndexPath:

Rápido :

textView.sizeToFit()

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

Por código

textView.scrollEnabled = false

Por storyboard

Desmarque o Rolagem habilitada

enter image description here

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

Na minha experiência (limitada),

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

não respeita caracteres de nova linha, então você pode acabar com caracteres muito mais curtos CGSize do que é realmente 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, defini a nova altura do UITextView ser 24 pixels maior que a altura retornada pelo sizeOfFont métodos.

No iOS6, você pode verificar o contentSize propriedade de UITextView logo após você definir o texto.No iOS7, isso não funcionará mais.Se você deseja restaurar esse comportamento para iOS7, coloque o código a seguir 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;
    }
}

Postarei a solução correta no final 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 quem não quer ler todo esse texto: redimensionávelTextView

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

Eu acho que todo código relacionado a restrições deveria ir para updateConstraints método.Então, vamos fazer o nosso próprio ResizableTextView.

O primeiro problema que encontramos aqui é que não sabemos o tamanho real do conteúdo antes viewDidLoad método.Podemos seguir um caminho longo e cheio de erros e calculá-lo 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)];

Então agora sabemos o contentSize real, não importa onde estejamos:antes ou depois viewDidLoad.Agora adicione restrição de altura em 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 para updateConstraints.

[super updateConstraints];

Agora nossa classe se parece com:

RedimensionávelTextView.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 seu controladores!

Mas espere! SEM ANIMAÇÃO!

Você pode facilmente animar alterações para fazer textView esticar suavemente.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];

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

Editar: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 vai caber perfeitamente no conteúdo que você deseja, mas é a primeira coisa a tentar.

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

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

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

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

Se você não tem o UITextView útil (por exemplo, você está dimensionando células de visualização de tabela), você terá que calcular o tamanho medindo a string e, em seguida, contabilizando os 8 pt de preenchimento em cada lado de um UITextView.Por exemplo, se você sabe a largura desejada da sua visualizaçã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 bordas acolchoadas e 100.000 serve apenas como um tamanho máximo muito grande.

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

As seguintes coisas são suficientes:

  1. Apenas lembre-se de definir rolagem ativada para NÃO Para o seu UITextView:

enter image description here

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

Você pode até usar UITableViewAutomaticDimension.

Podemos fazer isso por restrições.

  1. Defina restrições de altura para UITextView.enter image description here

2.Crie 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;
    }];

}

então atualize sua restrição assim :)

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

[myTextView setDelegate: self];

...

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

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

Pessoal, usando autolayout e seu sizetofit não está 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 perdi 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 ..

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.coloquei um projeto GitHub isso demonstra isso em ação, mas aqui está a chave:

  1. O UITextView deve ter a rolagem desabilitada, o que você pode fazer de forma programática ou por meio do construtor de interface.Ele não será redimensionado se a rolagem estiver habilitada porque a rolagem permite visualizar o conteúdo maior.
  2. Em viewDidLoad para UITableViewController, você deve definir um valor para estimativaRowHeight e, em seguida, definir o valor rowHeight para 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.

Isso funcionou muito bem quando eu precisei criar texto em um UITextView caber em uma área específica:

// The text must already be added to the subview, or contentviewsize will be wrong.

- (void) reduceFontToFit: (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 size:pointSize];
        tv.font = newFont;
    }
    if (pointSize != font.pointSize)
        NSLog(@"font down to %.1f from %.1f", pointSize, tv.font.pointSize);
}

aqui está a versão rápida de @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

Revisei todas as respostas e todas mantêm a largura fixa e ajustam apenas a altura.Se você deseja ajustar também a largura, você pode facilmente usar este método:

então, ao configurar sua visualização de texto, desative a rolagem

textView.isScrollEnabled = false

e depois 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:

enter image description here

enter image description here

desabilitar rolagem

adicionar restrições

e adicione seu texto

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

se você usar UIScrollView você deve adicionar isso 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;
}

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

Ver essa questão.

Espero que isto ajude:

- (void)textViewDidChange:(UITextView *)textView {
  CGSize textSize = textview.contentSize;
  if (textSize != textView.frame.size)
      textView.frame.size = textSize;
}

se algum outro chegar aqui, esta solução funciona para mim, 1"Ronnie Liew"+4"user63934" (Meu texto chega do serviço web):observe o 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

A melhor maneira que descobri de 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];

Para aqueles que desejam que a visualização do 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);
}

O único código que funcionará é aquele que usa 'SizeToFit' como na resposta do jhibberd acima, mas na verdade ele não funcionará a menos que você o chame VerDidAppear ou conecte-o ao evento de alteração de texto do UITextView.

Com base na resposta de Nikita Took cheguei à seguinte solução em 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
            }
        }
    }

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

Aqui está a resposta se você precisar redimensionar textView e tableViewCell dinamicamente em staticTableView

[https://stackoverflow.com/a/43137182/5360675][1]

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top