Pergunta

Eu tenho o seguinte código ...

UILabel *buttonLabel = [[UILabel alloc] initWithFrame:targetButton.bounds];
buttonLabel.text = @"Long text string";
[targetButton addSubview:buttonLabel];
[targetButton bringSubviewToFront:buttonLabel];

... a idéia é que eu posso ter múltiplas linhas de texto para o botão, mas o texto é sempre obscurecida pela backgroundImage do UIButton. Uma chamada de registro para mostrar os subviews do botão mostra que o UILabel foi adicionado, mas o texto em si não pode ser visto. É este um bug no UIButton ou estou fazendo algo errado?

Foi útil?

Solução

Para iOS 6 e superior, utilizar o que se segue para permitir que várias linhas:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
// you probably want to center it
button.titleLabel.textAlignment = NSTextAlignmentCenter; // if you want to 
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];

Para iOS 5 e a seguir utilizar o seguinte para permitir que várias linhas:

button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
// you probably want to center it
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];

2017, para iOS9 frente ,

Geralmente, apenas fazer essas duas coisas:

  1. escolha "Texto Atribuído"
  2. no pop-up "Quebra de Linha", selecione "Word Wrap"

Outras dicas

A resposta escolhida está correta, mas se você preferir fazer esse tipo de coisa no Interface Builder você pode fazer isso:

pic

Se você quiser adicionar um botão com o título centrado com várias linhas, definir as configurações do seu Interface Builder para o botão:

[aqui]

Para IOS 6:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;

Como

UILineBreakModeWordWrap and UITextAlignmentCenter

são preteridos em IOS 6 em diante ..

Para reafirmar a sugestão de Roger Nolan, mas com código explícito, esta é a solução geral:

button.titleLabel?.numberOfLines = 0

SWIFT 3

button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center  
button.setTitle("Button\nTitle",for: .normal)

Há uma maneira muito mais fácil:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(Edit para iOS 3 e mais tarde:)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

Alinhar à esquerda na iOS7 com autolayout:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;

Em primeiro lugar, você deve estar ciente de que UIButton já tem um UILabel dentro dela. Você pode configurá-lo usando –setTitle:forState:.

O problema com o seu exemplo é que você precisa para definir a propriedade numberOfLines do UILabel para algo diferente de seu valor padrão de 1. Você também deve rever a propriedade lineBreakMode.

No Xcode 9.3, você pode fazê-lo usando storyboard como abaixo,

 enter descrição da imagem aqui

Você precisa definir TextAlignment título do botão ao centro

button.titleLabel?.textAlignment = .center

Você não precisa de texto do título conjunto com nova linha (\ n) como abaixo,

button.setTitle("Good\nAnswer",for: .normal)

Simplesmente título definido,

button.setTitle("Good Answer",for: .normal)

Aqui está o resultado,

 enter descrição da imagem aqui

Para aqueles que estão usando storyboard Xcode 4 de, você pode clicar no botão e no painel Utilities lado direito em Atributos Inspector, você verá uma opção para quebra de linha. Escolha Word Wrap, e você deve ser bom para ir.

As respostas aqui dizer-lhe como conseguir título do botão de múltiplas linhas de programação.

Eu só queria acrescentar que, se você estiver usando storyboards, você pode digitar [Ctrl + Enter] para forçar uma nova linha em um campo de título do botão.

HTH

Você tem que adicionar este código:

buttonLabel.titleLabel.numberOfLines = 0;

Como a ideia do Brent de colocar o título UILabel como irmão vista, não me parece uma idéia muito boa. Eu fico pensando em problemas de interação com o UILabel devido aos seus eventos de toque não recebendo através da visão da UIButton.

Por outro lado, com uma UILabel como subexibição do UIButton, estou bastante confortável sabendo que os eventos de toque sempre será propagada para superview do UILabel.

Eu fiz tomar essa atitude e não notou qualquer um dos problemas relatados com backgroundImage. Eu adicionei este código no -titleRectForContentRect: de um UIButton subclasse mas o código também pode ser colocado na elaboração de rotina do superview UIButton, que nesse caso você deve substituir todas as referências à auto com variável da UIButton

.
#define TITLE_LABEL_TAG 1234

- (CGRect)titleRectForContentRect:(CGRect)rect
{   
    // define the desired title inset margins based on the whole rect and its padding
    UIEdgeInsets padding = [self titleEdgeInsets];
    CGRect titleRect = CGRectMake(rect.origin.x    + padding.left, 
                                  rect.origin.x    + padding.top, 
                                  rect.size.width  - (padding.right + padding.left), 
                                  rect.size.height - (padding.bottom + padding].top));

    // save the current title view appearance
    NSString *title = [self currentTitle];
    UIColor  *titleColor = [self currentTitleColor];
    UIColor  *titleShadowColor = [self currentTitleShadowColor];

    // we only want to add our custom label once; only 1st pass shall return nil
    UILabel  *titleLabel = (UILabel*)[self viewWithTag:TITLE_LABEL_TAG];


    if (!titleLabel) 
    {
        // no custom label found (1st pass), we will be creating & adding it as subview
        titleLabel = [[UILabel alloc] initWithFrame:titleRect];
        [titleLabel setTag:TITLE_LABEL_TAG];

        // make it multi-line
        [titleLabel setNumberOfLines:0];
        [titleLabel setLineBreakMode:UILineBreakModeWordWrap];

        // title appearance setup; be at will to modify
        [titleLabel setBackgroundColor:[UIColor clearColor]];
        [titleLabel setFont:[self font]];
        [titleLabel setShadowOffset:CGSizeMake(0, 1)];
        [titleLabel setTextAlignment:UITextAlignmentCenter];

        [self addSubview:titleLabel];
        [titleLabel release];
    }

    // finally, put our label in original title view's state
    [titleLabel setText:title];
    [titleLabel setTextColor:titleColor];
    [titleLabel setShadowColor:titleShadowColor];

    // and return empty rect so that the original title view is hidden
    return CGRectZero;
}

Eu fiz exame do momento e escreveu um pouco mais sobre este aqui . Lá, eu também apontam uma solução mais curto, embora não se encaixa todos os cenários e envolve alguns pontos de vista particulares de hackers. Também lá, você pode baixar um UIButton subclasse pronto para ser usado.

Se você usar o layout automático no iOS 6 que você pode também precisa definir a propriedade preferredMaxLayoutWidth:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.preferredMaxLayoutWidth = button.frame.size.width;

Ele funciona perfeitamente.

Adicionar a usar isso com arquivo de configuração como Plist, você precisa usar CDATA para escrever o título multilined, como este:

<string><![CDATA[Line1
Line2]]></string>

Configuração lineBreakMode para NSLineBreakByWordWrapping (seja em IB ou código) faz etiqueta do botão várias linhas, mas não afeta a estrutura do botão.

Se o botão tem o título dinâmico, há um truque: coloque escondido UILabel com o mesmo tipo de letra e amarrá-lo de altura até a altura do botão com disposição; quando o texto conjunto para botão e rótulo e autolayout vai fazer todo o trabalho.

Nota

Intrínseca altura tamanho do botão de uma linha é maior do que o rótulo de, de modo a evitar a altura do rótulo encolher é vertical, Prioridade Abraçando o conteúdo deve ser maior conteúdo verticais do botão de resistência à compressão.

Se você usar auto-layout.

button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2

Eu tive um problema com auto-layout, depois de ativar multi-linha o resultado foi como esta:
enter descrição da imagem aqui
assim o tamanho titleLabel não afeta o tamanho do botão
Eu adicionei Constraints baseado em contentEdgeInsets (neste caso contentEdgeInsets era (10, 10, 10, 10)
depois de chamar makeMultiLineSupport():
enter descrição da imagem aqui
espero que o ajude (SWIFT 5.0):

extension UIButton {

    func makeMultiLineSupport() {
        guard let titleLabel = titleLabel else {
            return
        }
        titleLabel.numberOfLines = 0
        titleLabel.setContentHuggingPriority(.required, for: .vertical)
        titleLabel.setContentHuggingPriority(.required, for: .horizontal)
        addConstraints([
            .init(item: titleLabel,
                  attribute: .top,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .top,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.top),
            .init(item: titleLabel,
                  attribute: .bottom,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .bottom,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.bottom),
            .init(item: titleLabel,
                  attribute: .left,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .left,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.left),
            .init(item: titleLabel,
                  attribute: .right,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .right,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.right)
            ])
    }

}

Hoje em dia, se você realmente precisa deste tipo de coisa para ser acessível em construtor de interface numa base caso-a-caso, você pode fazê-lo com uma extensão simples como isto:

extension UIButton {
    @IBInspectable var numberOfLines: Int {
        get { return titleLabel?.numberOfLines ?? 1 }
        set { titleLabel?.numberOfLines = newValue }
    }
}

Em seguida, você pode simplesmente definir numberOfLines como um atributo em qualquer UIButton ou UIButton subclasse como se fosse um rótulo. O mesmo vale para toda uma série de outros valores normalmente-inacessíveis, como o raio de canto da camada de um ponto de vista, ou os atributos da sombra que ele projeta.

Roll sua própria classe botão. É de longe a melhor solução a longo prazo. UIButton e outras classes UIKit são muito restritivas na forma como você pode personalizá-los.

self.btnError.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping

self.btnError.titleLabel?.textAlignment = .center

self.btnError.setTitle("Title", for: .normal)

rápida 4.0

btn.titleLabel?.lineBreakMode = .byWordWrapping
btn.titleLabel?.textAlignment = .center
btn.setTitle( "Line1\nLine2", for: .normal)

resposta dentro de STAButton que faz parte do meu STAControls biblioteca de código aberto. Actualmente, eu usá-lo dentro de um dos aplicativos que eu estou em desenvolvimento e que trabalha para as minhas necessidades. Sinta-se livre para questões em aberto sobre como melhorá-lo ou enviá-me puxar pedidos.

Swift 5.0 e Xcode 10.2

SharedClass exemplo escrever uma vez e utilizar todos os utensílios

Esta é a sua classe compartilhada (como este que você use todas as propriedades componentes)

import UIKit

class SharedClass: NSObject {

     static let sharedInstance = SharedClass()

     private override init() {

     }
  }

//UIButton extension
extension UIButton {
     //UIButton properties
     func btnMultipleLines() {
         titleLabel?.numberOfLines = 0
         titleLabel?.lineBreakMode = .byWordWrapping
         titleLabel?.textAlignment = .center        
     }
}

Em sua ViewController chamada como esta

button.btnMultipleLines()//This is your button

Embora não há problema em adicionar um subexibição a um controle, não há nenhuma garantia de que vai realmente trabalhar, porque o controle não pode esperar que ele esteja lá e poderia, assim, se comportam mal. Se você pode obter afastado com ele, basta adicionar o rótulo como uma visão irmão do botão e definir o seu quadro, de modo que se sobreponha o botão; contanto que ele está definido para aparecer no topo do botão, nada o botão possa fazer vai obscurecer-lo.

Em outras palavras:

[button.superview addSubview:myLabel];
myLabel.center = button.center;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top