UIButton com duas linhas de texto no título (numberOfLines = 2)

86

Estou tentando fazer um UIButtonque tenha duas linhas de texto em seu titleLabel. Este é o código que estou usando:

    UIButton *titleButton = [[UIButton alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
    titleButton.titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
    [titleButton setTitle:@"This text is very long and should get truncated at the end of the second line" forState:UIControlStateNormal];
    titleButton.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
    titleButton.titleLabel.numberOfLines = 2;
    [self addSubview:titleButton];

Quando tento fazer isso, o texto só aparece em uma linha. Parece que a única maneira de obter mais de uma linha de texto UIButton.titleLabelé definir numberOfLines=0e usar UILineBreakModeWordWrap. Mas isso não garante que o texto tenha exatamente duas linhas.

Usar uma planície UILabel, no entanto, funciona:

    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
    titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
    titleLabel.text = @"This text is very long and should get truncated at the end of the second line";
    titleLabel.numberOfLines = 2;
    titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
    [self addSubview:titleLabel];

Alguém sabe fazer o UIButtontrabalho com duas linhas? A única solução é criar um separado UILabelpara conter o texto e adicioná-lo como uma subvisão do botão?

comerciante
fonte
1
Você viu isso ? - stackoverflow.com/questions/604632/…
Viraj
Viraj, sim, se você definir numberOfLines=0e usar UILineBreakModeWordWrap, você pode obter várias linhas. O problema é que pode haver mais de duas linhas se o texto for muito longo. Eu quero exatamente dois solitários com reticências no final da segunda linha (se o texto for muito longo).
comerciante de
Oh, então eu acho que adicionar subvisão pode ser a única maneira de ir.
Viraj de

Respostas:

87

Resposta atualizada para versões mais recentes do iOS

Como esta é a resposta aceita, adicionou a resposta de @Sean aqui:

Defina essas propriedades no titleLabel do seu botão.

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2; // if you want unlimited number of lines put 0

Swift 3 e 4:

button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.numberOfLines = 2 // if you want unlimited number of lines put 0

Resposta original para uma versão mais antiga do iOS

Se você quiser 2 linhas de texto sobre o seu, UIButtondeve adicionar um UIlabelque faça exatamente isso.

UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 10, frame.size.width-100, 100)];
titleLabel.font = [UIFont boldSystemFontOfSize:24.0];
titleLabel.text = @"This text is very long and should get truncated at the end of the second line";
titleLabel.numberOfLines = 2;
titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
[myButton addSubview:titleLabel]; //add label to button instead.

Atualizado para solução de construtor de interface

Adicionada a resposta de @Borut Tomazin para uma resposta mais completa. Atualizada esta parte novamente já que a resposta de @Borut Tomazin foi melhorada.

Você pode fazer isso muito mais fácil, sem a necessidade de código. Em Interface Builder definido Line Breakem UIButton para Word Wrap. Depois, você pode inserir várias linhas de título. Basta apertar as Option + Returnteclas para fazer uma nova linha. Você também precisará adicioná-lo ao Atributo de tempo de execução definido pelo usuário no Interface Builder:

titleLabel.textAlignment Number [1]
Totumus Maximus
fonte
5
UILineBreakModeestão obsoletos, use em NSLineBreakModevez deles
guillaume
2
Isso é desnecessário nas versões recentes do iOS. Veja a resposta de @sean.
cbowns
146

Você não precisa adicionar um UILabel ao UIButton. São apenas objetos extras e trabalho.

Defina essas propriedades no titleLabel do seu botão.

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2;//if you want unlimited number of lines put 0

Rápido:

button.titleLabel!.lineBreakMode = NSLineBreakMode.ByWordWrapping
button.titleLabel!.numberOfLines = 2//if you want unlimited number of lines put 0
Sean
fonte
6
Este é o 2013 e, a partir de hoje, esta é a solução de ponta.
Klaas
@Blip você não pode infelizmente e precisa fazer isso em código. Pode valer a pena preencher um relatório de bug com a Apple solicitando essa funcionalidade.
bpapa
@bpapa Sim, concordo, os storyboards devem ser mais flexíveis.
Blip
6
Isso funciona para mim, porém quebra o comportamento padrão do botão intrinsicContentSize, que ainda retorna uma altura que corresponde a apenas uma linha de texto. Eu consertei substituindo o botão intrinsicContentSizeonde defini a altura [self.titleLabel sizeThatFits(CGSizeMake(self.titleLabel.frame.size.width, CGFLOAT_MAX)].height.
Elise
@WillVonUllrich porque você só pode alterar a resposta aceita quando ela é editada. Eu adicionei essas respostas à aceita para ajudar as pessoas que não procuram além da resposta aceita.
Totumus Maximus
88

Você pode fazer isso muito mais fácil, sem a necessidade de código. Em Interface Builder definido Line Breakem UIButton para Word Wrap. Depois, você pode inserir várias linhas de título. Basta apertar as Option + Returnteclas para fazer uma nova linha. Você também precisará adicioná-lo ao Atributo de tempo de execução definido pelo usuário no Interface Builder:

titleLabel.textAlignment Number [1]

É simples assim. Espero que ajude...

Borut Tomazin
fonte
1
Esta solução é melhor (menos objetos, código) do que a atualmente aceita, para casos simples.
Jonathan Zhan
1
Você define exatamente as mesmas propriedades que definiria programaticamente, de modo que seu argumento "menos objetos" é inválido. O código talvez seja menor. Mas é mais legível. Faça sua escolha;)
Totumus Maximus
Oh, eu não estava claro, eu acho. Obrigado por tentar esclarecer. Não estava muito preocupado com o fato de ser feito em IB vs Código. Mais a ver com o fato de que você não precisa adicionar um rótulo adicional com a solução de Borut, e que ela também realiza a mesma coisa. Mas sim, ambos funcionam muito bem. :)
Jonathan Zhan
é realmente opressor precisar ir atrás do código para uma tarefa tão básica.
Can Poyrazoğlu
3
Você pode atingir o mesmo objetivo 100% sem código adicionando o titleLabel.textAlignment Atributo de Tempo de Execução Definido pelo Usuário no Construtor de Interface e configurando-o como Número = 1 (valor do NSTextAlignmentCenter).
0xced
21
 button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;

button.titleLabel.textAlignment = NSTextAlignmentCenter;

[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];
Suraj K Thomas
fonte
Perfeito! Você não tem que dividir o NSStringinterior setTitle. `WordWrapping`` está fazendo isso por você!
Alex Cio
Para mim, eu tive que dividir a string dentro do título definido. Sem isso não funcionou
user1960169
9

Para evitar completamente a necessidade de editar o código e, portanto, a necessidade de criar uma subclasse de sua visualização, no Xcode5 e superior, você pode seguir a sugestão de Borut Tomazin:

No Interface Builder (ou storyboard), defina a quebra de linha para quebra de linha. Depois, você pode inserir várias linhas de título. Basta pressionar as teclas Option+ Returnpara fazer uma nova linha.

e então, nos Atributos de tempo de execução definidos pelo usuário, você pode adicionar

Caminho da chave: titleLabel.textAlignment
Tipo: Number
Valor:1

Observação: isso pode não ser totalmente "à prova de futuro", pois estamos traduzindo a UITextAlignmentCenterconstante em seu valor numérico (e essa constante pode mudar conforme novas versões do iOS são lançadas), mas parece seguro em um futuro próximo.

furins
fonte
0

Você pode modificar o valor necessário diretamente do Storyboard. Selecione o botão, vá para o inspetor de identidade e adicione o seguinte par de valores-chave na seção "Atributos de tempo de execução definidos pelo usuário":

insira a descrição da imagem aqui

Arik Segal
fonte