Estou um pouco atrasado para esta festa, mas acho que tenho algo útil a acrescentar.
A resposta de Kekoa é ótima, mas, como RonLugge menciona, ele pode fazer com que o botão não seja mais respeitado sizeToFit
ou, mais importante, pode fazer com que o botão recorte seu conteúdo quando ele é intrinsecamente dimensionado. Caramba!
Primeiro, porém,
Uma breve explicação de como acredito imageEdgeInsets
e titleEdgeInsets
trabalho:
Os documentos paraimageEdgeInsets
têm o seguinte a dizer, em parte:
Use esta propriedade para redimensionar e reposicionar o retângulo de desenho efetivo para a imagem do botão. Você pode especificar um valor diferente para cada uma das quatro inserções (superior, esquerda, inferior, direita). Um valor positivo diminui ou insere essa borda - aproximando-o do centro do botão. Um valor negativo expande ou ultrapassa essa margem.
Acredito que esta documentação foi escrita imaginando que o botão não tem título, apenas uma imagem. Faz muito mais sentido pensar dessa maneira e se comporta como UIEdgeInsets
costuma fazer. Basicamente, o quadro da imagem (ou o título, com titleEdgeInsets
) é movido para dentro para inserções positivas e para fora para inserções negativas.
Tá, e daí?
Estou chegando lá! Aqui está o que você tem por padrão, definindo uma imagem e um título (a borda do botão é verde apenas para mostrar onde está):
Quando você deseja espaçar entre uma imagem e um título, sem causar esmagamento, é necessário definir quatro inserções diferentes, duas em cada imagem e título. Isso ocorre porque você não deseja alterar os tamanhos dos quadros desses elementos, mas apenas suas posições. Quando você começa a pensar dessa maneira, a mudança necessária para a excelente categoria de Kekoa fica clara:
@implementation UIButton(ImageTitleCentering)
- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing {
CGFloat insetAmount = spacing / 2.0;
self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount);
self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount);
}
@end
Mas espere , você diz, quando faço isso, recebo o seguinte:
Oh sim! Eu esqueci, os documentos me avisaram sobre isso. Eles dizem, em parte:
Esta propriedade é usada apenas para posicionar a imagem durante o layout. O botão não usa essa propriedade para determinar intrinsicContentSize
e sizeThatFits:
.
Mas não é uma propriedade que pode ajudar, e isso é contentEdgeInsets
. Os documentos para isso dizem, em parte:
O botão usa essa propriedade para determinar intrinsicContentSize
e sizeThatFits:
.
Isso soa bem. Então, vamos ajustar a categoria mais uma vez:
@implementation UIButton(ImageTitleCentering)
- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing {
CGFloat insetAmount = spacing / 2.0;
self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount);
self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount);
self.contentEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, insetAmount);
}
@end
e o que você ganha?
Parece um vencedor para mim.
Trabalhando na Swift e não quer pensar em nada? Aqui está a versão final da extensão no Swift:
extension UIButton {
func centerTextAndImage(spacing: CGFloat) {
let insetAmount = spacing / 2
imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount, bottom: 0, right: insetAmount)
titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: -insetAmount)
contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
}
}