Como você adiciona o texto multi-linha para uma UIButton?
-
03-07-2019 - |
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?
Solução
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
// you probably want to center it
button.titleLabel.textAlignment = NSTextAlignmentCenter; // if you want to
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];
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:
- escolha "Texto Atribuído"
- 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:
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:
[]
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,
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,
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 ??strong>
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:
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()
:
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.
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 ??p>
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;