Para o que vale, aqui está uma solução geral para posicionar a imagem centralizada acima do texto sem usar números mágicos. Observe que o código a seguir está desatualizado e você provavelmente deve usar uma das versões atualizadas abaixo :
// the space between the image and text
CGFloat spacing = 6.0;
// lower the text and push it left so it appears centered
// below the image
CGSize imageSize = button.imageView.frame.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
// raise the image and push it right so it appears centered
// above the text
CGSize titleSize = button.titleLabel.frame.size;
button.imageEdgeInsets = UIEdgeInsetsMake(
- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
A versão a seguir contém alterações no iOS 7+ recomendadas nos comentários abaixo. Eu não testei esse código pessoalmente, então não tenho certeza de como ele funciona ou se ele seria quebrado se usado nas versões anteriores do iOS.
// the space between the image and text
CGFloat spacing = 6.0;
// lower the text and push it left so it appears centered
// below the image
CGSize imageSize = button.imageView.image.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
// raise the image and push it right so it appears centered
// above the text
CGSize titleSize = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}];
button.imageEdgeInsets = UIEdgeInsetsMake(
- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
// increase the content height to avoid clipping
CGFloat edgeOffset = fabsf(titleSize.height - imageSize.height) / 2.0;
button.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0);
Versão Swift 5.0
extension UIButton {
func alignVertical(spacing: CGFloat = 6.0) {
guard let imageSize = imageView?.image?.size,
let text = titleLabel?.text,
let font = titleLabel?.font
else { return }
titleEdgeInsets = UIEdgeInsets(
top: 0.0,
left: -imageSize.width,
bottom: -(imageSize.height + spacing),
right: 0.0
)
let titleSize = text.size(withAttributes: [.font: font])
imageEdgeInsets = UIEdgeInsets(
top: -(titleSize.height + spacing),
left: 0.0,
bottom: 0.0, right: -titleSize.width
)
let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0
contentEdgeInsets = UIEdgeInsets(
top: edgeOffset,
left: 0.0,
bottom: edgeOffset,
right: 0.0
)
}
}
button.currentTitle
vez de,button.titleLabel.text
especialmente se o texto do botão mudar.currentTitle
é preenchido imediatamente, enquantotitleLabel.text
a mudança pode ser lenta, o que pode levar a inserções desalinhadas.Encontrado como.
Primeiro, configure o texto de
titleLabel
(por causa de estilos, como negrito, itálico etc.). Em seguida, usesetTitleEdgeInsets
considerando a largura da sua imagem:Depois disso, use
setTitleEdgeInsets
considerando a largura dos limites do texto:Agora a imagem e o texto serão centralizados (neste exemplo, a imagem aparece acima do texto).
Felicidades.
fonte
Você pode fazer isso com esta extensão Swift, que foi parcialmente baseada na resposta de Jesse Crossen:
Isso define uma função
centerLabelVerticallyWithPadding
que define o título e a imagem adequadamente.Ele também define o contentEdgeInsets, que acredito ser necessário para garantir que
intrinsicContentSize
ainda funcione corretamente, o que precisaria usar o Layout automático.Acredito que todas as soluções que subclasses UIButton são tecnicamente ilegítimas, já que você não deve subclassificar os controles UIKit. Ou seja, em teoria, eles podem quebrar em versões futuras.
fonte
Edit: Atualizado para Swift 3
Caso esteja procurando uma solução rápida da resposta de Jesse Crossen, você pode adicioná-lo a uma subclasse de UIButton:
fonte
Existem alguns exemplos excelentes aqui, mas eu não consegui fazer isso funcionar em todos os casos quando também lida com várias linhas de texto (quebra de texto). Para finalmente fazê-lo funcionar, combinei algumas das técnicas:
Eu usei o exemplo de Jesse Crossen acima. No entanto, corrigi um problema de altura do texto e adicionei a capacidade de especificar uma margem de texto horizontal. A margem é útil ao permitir a quebra do texto para que não atinja a borda do botão:
Certifique-se de configurar o rótulo do texto para quebrar
Isso funcionará principalmente agora. No entanto, eu tinha alguns botões que não renderizavam sua imagem corretamente. A imagem foi deslocada para a direita ou esquerda (não estava centralizada). Então, usei uma técnica de substituição de layout UIButton para forçar o imageView a ser centralizado.
fonte
Eu criei um método para a resposta de @ TodCunningham
fonte
Atualizado para o Xcode 11+
As inserções descritas na minha resposta original foram movidas para o inspetor de tamanho nas versões mais recentes do Xcode. Não estou 100% claro quando a troca aconteceu, mas os leitores devem revisar o inspetor de tamanho se as informações inseridas não forem encontradas no inspetor de atributos. Abaixo está uma amostra da nova tela de inserção (localizada na parte superior do inspetor de atributos de tamanho a partir de 11.5).
Resposta original
Nada de errado com as outras respostas, no entanto, eu só queria observar que o mesmo comportamento pode ser realizado visualmente no Xcode usando zero linhas de código. Esta solução é útil se você não precisar de um valor calculado ou estiver construindo com um storyboard / xib (caso contrário, outras soluções se aplicam).
Nota - Entendo que a pergunta do OP é uma que exige código. Estou apenas fornecendo esta resposta para que seja completa e como uma alternativa lógica para aqueles que usam storyboards / xibs.
Para modificar o espaçamento nas visualizações de imagem, título e conteúdo de um botão usando inserções de borda, você pode selecionar o botão / controle e abrir o inspetor de atributos. Role para baixo em direção ao meio do inspetor e localize a seção Inserir borda.
Também é possível acessar e modificar as inserções de borda específicas para a exibição de título, imagem ou conteúdo.
fonte
Não lute contra o sistema. Se seus layouts se tornarem complexos demais para gerenciar usando o Interface Builder + talvez algum código de configuração simples, faça os layouts manualmente de maneira mais simples
layoutSubviews
- é para isso que serve! Tudo o resto equivale a hacks.Crie uma subclasse UIButton e substitua seu
layoutSubviews
método para alinhar seu texto e imagem programaticamente. Ou use algo como https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h para poder implementar layoutSubviews usando um bloco.fonte
Subclasse UIButton
fonte
Resposta atualizada de Jesse Crossen para Swift 4 :
Use desta maneira:
fonte
Com esse pedaço de código, você obterá algo como isto
fonte
Extensão UIButton com sintaxe do Swift 3+ :
Resposta original: https://stackoverflow.com/a/7199529/3659227
fonte
Apenas uma pequena alteração na resposta de Jesse Crossen que a fez funcionar perfeitamente para mim:
ao invés de:
Eu usei isso:
fonte
O uso
button.titleLabel.frame.size.width
funciona bem apenas desde que a etiqueta seja curta o suficiente para não ser truncada. Quando o texto da etiqueta é truncado, o posicionamento não funciona. Levandofunciona para mim mesmo quando o texto da etiqueta está truncado.
fonte
Examinei as respostas existentes, mas também achei que definir o quadro dos botões é um primeiro passo importante.
Aqui está uma função que eu uso que cuida disso:
fonte
Ou você pode apenas usar esta categoria:
fonte
CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName: button.titleLabel.font}];
Meu caso de uso tornou as inserções incontroláveis:
Foi o que acabei fazendo e estou muito feliz com isso:
Crie o botão no storyboard com uma imagem de fundo (círculo redondo com desfoque e cor).
Declare um UIImageView na minha classe:
Crie uma instância de visualização de imagem no init:
Em viewDidLoad, adicione uma nova camada ao botão para a visualização da imagem e defina o alinhamento do texto:
No método de clique no botão, adicione a imagem de sobreposição escolhida à visualização da imagem, dimensione-a para caber na imagem e centralize-a no botão, mas mova-a para cima 15 para que eu possa colocar o texto abaixo dela:
Nota: ceilf () é importante para garantir um limite de pixel para a qualidade da imagem.
fonte
Supondo que você deseja que o texto e a imagem sejam centralizados horizontalmente, imagem acima do texto: centralize o texto do construtor de interface e adicione uma inserção superior (abrindo espaço para a imagem). (deixe a esquerda inserida em 0). Use o construtor de interface para escolher a imagem - sua posição real será definida a partir do código; portanto, não se preocupe, pois as coisas não parecerão boas no IB. Diferente das outras respostas acima, isso realmente funciona em todas as versões do iOS atualmente suportadas (5,6 e 7).
No código, apenas descarte o ImageView do botão (configurando a imagem do botão como nula) depois de capturar a imagem (isso também centralizará automaticamente o texto, se necessário). Instancie seu próprio ImageView com o mesmo tamanho de quadro e imagem e posicione-o no meio.
Dessa forma, você ainda pode escolher a imagem no construtor de interface (embora ela não seja alinhada no IB como no simulador, mas, novamente, outras soluções não são compatíveis em todas as versões do iOS suportadas)
fonte
Eu estava lutando para fazer isso porque não conseguia obter o tamanho da imagem e a largura do texto no construtor da minha exibição. Duas pequenas mudanças na resposta de Jesse funcionaram para mim:
As mudanças são:
[NSString sizeWithAttributes]
para obter a largura do texto;UIImage
lugar deUIImageView
fonte
Isso funciona bem para mim, para vários botões, com largura de imagem diferente e comprimento de título diferente:
Subclasse
UIButton
fonte
Funcionando bem para o tamanho do botão 80x80 pixels.
fonte
Fiz alguns ajustes para alinhar a imagem no centro horizontal:
fonte
é obrigatório usar insertos de borda? Caso contrário, você pode tentar posicionar o respeito à vista principal central
fonte
Você precisa mover a imagem para a direita pela largura do texto. Em seguida, mova o texto para a esquerda pela largura da imagem.
Em seguida, ajuste as inserções superior e inferior para ajustar o eixo Y. Provavelmente, isso também pode ser feito programaticamente, mas deve ser constante para o tamanho da imagem. Enquanto as inserções do eixo X precisarão ser alteradas com base no tamanho do rótulo do texto em cada botão.
fonte
Adicione este código na extensão Swift 4.2
fonte
Apenas para jogar meus 2 centavos, isso funcionou para mim:
fonte