UILabel - etiqueta de tamanho automático para caber no texto?


144

É possível redimensionar automaticamente a caixa / limites do UILabel para caber no texto contido? (Não me importo se ele for maior que a tela)

Portanto, se um usuário digitar "olá" ou "meu nome for muito longo, quero que ele caiba nesta caixa", ele nunca será truncado e o rótulo será 'ampliado' adequadamente?


Qualquer um me ajuda por favor com o fornecimento de códigos rápidos ..
Anjo F Syrus

Respostas:


98

Por favor, verifique minha essência onde eu fiz uma categoria para UILabelalgo muito semelhante; minha categoria permite UILabelesticar sua altura para mostrar todo o conteúdo: https://gist.github.com/1005520

Ou confira esta publicação: https://stackoverflow.com/a/7242981/662605

Isso aumentaria a altura, mas você pode alterá-la facilmente para trabalhar de outra maneira e aumentar a largura com algo parecido com isto, que é o que você deseja fazer:

@implementation UILabel (dynamicSizeMeWidth)

- (void)resizeToStretch{
    float width = [self expectedWidth];
    CGRect newFrame = [self frame];
    newFrame.size.width = width;
    [self setFrame:newFrame];
}

- (float)expectedWidth{
    [self setNumberOfLines:1];

    CGSize maximumLabelSize = CGSizeMake(CGRectGetWidth(self.bounds), CGFLOAT_MAX);

    CGSize expectedLabelSize = [[self text] sizeWithFont:[self font] 
                                            constrainedToSize:maximumLabelSize
                                            lineBreakMode:[self lineBreakMode]]; 
    return expectedLabelSize.width;
}

@end

Você poderia simplesmente usar o sizeToFitmétodo disponível na UIViewclasse, mas defina o número de linhas como 1 para ser seguro.


atualização para iOS 6

Se você estiver usando o AutoLayout, terá uma solução integrada. Ao definir o número de linhas como 0, a estrutura redimensionará seu rótulo adequadamente (adicionando mais altura) para caber no seu texto.


atualização para iOS 8

sizeWithFont:está obsoleto, então use sizeWithAttributes::

- (float)expectedWidth{
    [self setNumberOfLines:1];

    CGSize expectedLabelSize = [[self text] sizeWithAttributes:@{NSFontAttributeName:self.font}];

    return expectedLabelSize.width;
}

8
Usando o método AutoLayout do iOS 6, acabei com uma restrição de altura no rótulo que não conseguia me livrar. Definir a relação da restrição de altura como 'Maior que ou igual' permitiu que a altura aumentasse.
Michael Luton

2
sizeWithFont: constrainedToSize: lineBreakMode: método privado no ios 7
Karan Alangat

1
O UILabel não é redimensionado quando o texto é menor / maior. Estou usando o layout automático. Tentei criar UILabel, mas eles são criados sempre que cellForRowAtIndex é inicializado. Tentei muitas coisas. Nada funcionando para mim. O fundo do uilabel tem a mesma largura. Socorro !!!
coreDeviOS

@ Daniel Defino o número de linhas = 0, mas não está funcionando. Eu estabeleci as restrições do centro horizontal e vertical. Uma coisa extra que eu tenho feito é feita uma subclasse de UILabel e usá-lo para essa etiqueta
Jasmeet

Com o Autolayout, a solução mais simples para: (1) Defina linhas como 0, (2) Defina a restrição de largura como "Maior que ou igual" com a constante 0, (3) Defina a restrição de altura como "Maior que ou igual" com a constante 0, ( 4) Alinhe como faria normalmente, por exemplo, centralizando horizontal e verticalmente.
Erik van der Neut

76

A utilização [label sizeToFit];alcançará o mesmo resultado da categoria Daniels.

Embora eu recomendo usar o layout automático e deixar o rótulo se redimensionar com base em restrições.


3
Ao usar o swift, eu tive que executar isso no thread principal usando dispatch_async (dispatch_get_main_queue (), {});
Zeezer 24/03

@Zeezer você sabe o porquê?
93015 FurloSK

13
@FurloSK Quaisquer alterações na interface do usuário devem ser feitas no thread principal.
Guilherme Torres Castro

32

Se quisermos que isso UILabeldiminua e se expanda com base no tamanho do texto, o storyboard com autolayout é a melhor opção. Abaixo estão as etapas para conseguir isso

Passos

  1. Coloque o UILabel no controlador de exibição e coloque-o onde quiser. Também colocado 0para a numberOfLinespropriedade de UILabel.

  2. Dê a ela restrições de pino de espaço superior, à esquerda e à direita.

insira a descrição da imagem aqui

  1. Agora ele avisará: Clique na seta amarela.

insira a descrição da imagem aqui

  1. Clique em Update Framee clique em Fix Misplacement. Agora, esse UILabel será reduzido se o texto for menor e expandido se o texto for maior.

1
Eu não testei para localização, mas deve funcionar para isso também.
Yogesh Suthar

2
Não pude fazer isso funcionar com um projeto existente até desmarcar a caixa de seleção "Largura preferida" "Explícita", e tudo funcionou bem.
Zorro2b 22/09/16

25

Isso não é tão complicado quanto algumas das outras respostas.

insira a descrição da imagem aqui

Fixar as bordas esquerda e superior

Basta usar o layout automático para adicionar restrições para fixar os lados esquerdo e superior do rótulo.

insira a descrição da imagem aqui

Depois disso, ele será redimensionado automaticamente.

Notas

  • Não adicione restrições para a largura e altura. Os rótulos têm um tamanho intrínseco com base no conteúdo do texto.
  • Obrigado a esta resposta por ajuda com isso.
  • Não é necessário definir sizeToFitao usar o layout automático. Meu código completo para o projeto de exemplo está aqui:

    import UIKit
    class ViewController: UIViewController {
    
        @IBOutlet weak var myLabel: UILabel!
    
        @IBAction func changeTextButtonTapped(sender: UIButton) {
            myLabel.text = "my name is really long i want it to fit in this box"
        }
    }
  • Se você deseja que seu rótulo seja alinhado, defina o número de linhas como 0 no IB e adicione o myLabel.preferredMaxLayoutWidth = 150 // or whatevercódigo. Também fixei meu botão na parte inferior do rótulo para que ele se movesse para baixo quando a altura do rótulo aumentasse.

insira a descrição da imagem aqui

  • Se você estiver procurando etiquetas de dimensionamento dinâmico dentro de um UITableViewCell, consulte esta resposta .

insira a descrição da imagem aqui


Olá, recebi o rótulo redimensionado, mas não entendo como redimensionar a altura da célula. Você pode me informar como redimensionar a altura da célula.
Vivek

@Vivek, desde que você não tenha nenhuma restrição de altura, ela deve ser redimensionada automaticamente.
Suragch 8/11

Sim, mas como é possível quando eu uso uma célula personalizada e coloco uma etiqueta 2 na célula dele.
Vivek #

@ Vivive, desculpe, eu interpretei mal sua pergunta. Você já conseguiu um rótulo para trabalhar ao seguir esta resposta ?
217 Suragch


5

Criei alguns métodos com base na resposta de Daniel acima.

-(CGFloat)heightForLabel:(UILabel *)label withText:(NSString *)text
{
    CGSize maximumLabelSize     = CGSizeMake(290, FLT_MAX);

    CGSize expectedLabelSize    = [text sizeWithFont:label.font
                                constrainedToSize:maximumLabelSize
                                    lineBreakMode:label.lineBreakMode];

    return expectedLabelSize.height;
}

-(void)resizeHeightToFitForLabel:(UILabel *)label
{
    CGRect newFrame         = label.frame;
    newFrame.size.height    = [self heightForLabel:label withText:label.text];
    label.frame             = newFrame;
}

-(void)resizeHeightToFitForLabel:(UILabel *)label withText:(NSString *)text
{
    label.text              = text;
    [self resizeHeightToFitForLabel:label];
}

5

Aqui está o que estou encontrando funciona para a minha situação:

1) A altura do UILabel tem uma restrição> = 0 usando o layout automático. A largura é fixa. 2) Atribua o texto ao UILabel, que já possui uma superview nesse ponto (não tenho certeza da vitalidade). 3) Em seguida, faça:

    label.sizeToFit()
    label.layoutIfNeeded()

A altura do rótulo está agora definida adequadamente.


3
@implementation UILabel (UILabel_Auto)

- (void)adjustHeight {

    if (self.text == nil) {
        self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.bounds.size.width, 0);
        return;
    }

    CGSize aSize = self.bounds.size;
    CGSize tmpSize = CGRectInfinite.size;
    tmpSize.width = aSize.width;

    tmpSize = [self.text sizeWithFont:self.font constrainedToSize:tmpSize];

    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, aSize.width, tmpSize.height);
}

@end

Este é o método da categoria. Você deve definir o texto primeiro, depois chame esse método para ajustar a altura do UILabel.


2

Você pode dimensionar seu rótulo de acordo com o texto e outros controles relacionados usando duas maneiras:

  1. Para iOS 7.0 e superior

    CGSize labelTextSize = [labelText boundingRectWithSize:CGSizeMake(labelsWidth, MAXFLOAT)
                                              options:NSStringDrawingUsesLineFragmentOrigin
                                           attributes:@{
                                                        NSFontAttributeName : labelFont
                                                        }
                                              context:nil].size;

antes do iOS 7.0, isso poderia ser usado para calcular o tamanho da etiqueta

CGSize labelTextSize = [label.text sizeWithFont:label.font 
                            constrainedToSize:CGSizeMake(label.frame.size.width, MAXFLOAT)  
                                lineBreakMode:NSLineBreakByWordWrapping];

// renomear outros controles com base em labelTextHeight

CGFloat labelTextHeight = labelTextSize.height;
  1. Se você não deseja calcular o tamanho do texto do rótulo, pode usar -sizeToFit na instância do UILabel como-

    [label setNumberOfLines:0]; // for multiline label
    [label setText:@"label text to set"];
    [label sizeToFit];// call this to fit size of the label according to text

// depois disso, você pode fazer com que o quadro da etiqueta reformule outros controles relacionados


2
  1. Adicione restrições ausentes no storyboard.
  2. Selecione UILabel no storyboard e defina os atributos "Linha" como 0.
  3. Ref Faça a saída do UILabel para Controller.h com id: label
  4. Controller.m e adicione [label sizeToFit];em viewDidLoad

1

Eu tive um grande problema com o layout automático. Temos dois contêineres dentro da célula da tabela. O segundo contêiner é redimensionado, dependendo da descrição do item (0 - 1000 caracteres), e a linha deve ser redimensionada com base neles.

O ingrediente que faltava era a restrição de fundo para descrição.

Alterei a restrição inferior do elemento dinâmico de = 0 para > = 0 .


Isso salvou minha vida. Se você está tentando seguir: github.com/honghaoz/…, esta é a resposta correta.
Justin Fyles

0

Cabe sempre! :)

    name.text = @"Hi this the text I want to fit to"
    UIFont * font = 14.0f;
    CGSize size = [name.text sizeWithAttributes:@{NSFontAttributeName: font}];
    nameOfAssessment.frame = CGRectMake(400, 0, size.width, 44);
    nameOfAssessment.font = [UIFont systemFontOfSize:font];

0

você pode mostrar uma saída de linha e definir a propriedade Line = 0 e mostrar várias saídas de linha e definir a propriedade Line = 1 e mais

[self.yourLableName sizeToFit];

-1

Há também esta abordagem:

[self.myLabel changeTextWithAutoHeight:self.myStringToAssignToLabel width:180.0f];

Não fui eu quem votou negativamente nesta resposta, mas eu só queria ressaltar que não consigo ver um changeTextWithAutoHeight:width:método UILabel. Você poderia fornecer um link para onde, na documentação do UIKit, esse método pode ser encontrado.
Adil Hussain
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.