Para lo que vale, aquí hay una solución general para colocar la imagen centrada sobre el texto sin usar ningún número mágico. Tenga en cuenta que el siguiente código está desactualizado y probablemente debería usar una de las versiones actualizadas a continuación :
// 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);
La siguiente versión contiene cambios para admitir iOS 7+ que se han recomendado en los comentarios a continuación. No he probado este código yo mismo, así que no estoy seguro de qué tan bien funciona o si se rompería si se usara en versiones anteriores de 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);
Versión 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
lugar debutton.titleLabel.text
especialmente si el texto del botón cambiara alguna vez.currentTitle
se llena de inmediato, mientras quetitleLabel.text
puede cambiar lentamente, lo que puede conducir a insertos desalineados.Encontrado cómo.
Primero, configure el texto de
titleLabel
(debido a los estilos, es decir, negrita, cursiva, etc.). Luego, usesetTitleEdgeInsets
considerando el ancho de su imagen:Después de eso, use
setTitleEdgeInsets
considerando el ancho de los límites del texto:Ahora la imagen y el texto estarán centrados (en este ejemplo, la imagen aparece sobre el texto).
Salud.
fuente
Puede hacerlo con esta extensión Swift, que se basó en parte en la respuesta de Jesse Crossen:
Esto define una función
centerLabelVerticallyWithPadding
que establece el título y las inserciones de imagen de manera adecuada.También establece contentEdgeInsets, que creo que es necesario para garantizar que
intrinsicContentSize
todavía funcione correctamente, que necesitaría usar el diseño automático.Creo que todas las soluciones que subclase UIButton son técnicamente ilegítimas, ya que no se supone que subclase los controles UIKit. Es decir, en teoría podrían romperse en futuras versiones.
fuente
Editar: actualizado para Swift 3
En caso de que esté buscando una solución rápida de la respuesta de Jesse Crossen, puede agregar esto a una subclase de UIButton:
fuente
Aquí hay algunos ejemplos excelentes, pero no pude hacer que esto funcionara en todos los casos cuando también trataba con varias líneas de texto (ajuste de texto). Para que finalmente funcione, combiné un par de técnicas:
Usé el ejemplo anterior de Jesse Crossen. Sin embargo, solucioné un problema de altura del texto y agregué la capacidad de especificar un margen de texto horizontal. El margen es útil cuando permite que el texto se ajuste para que no toque el borde del botón:
Asegúrese de configurar la etiqueta de texto para ajustar
Esto funcionará principalmente ahora. Sin embargo, tenía algunos botones que no mostraban su imagen correctamente. La imagen se desplazó hacia la derecha o hacia la izquierda (no estaba centrada). Así que utilicé una técnica de anulación de diseño UIButton para forzar el centrado de imageView.
fuente
Hice un método para la respuesta de @ TodCunningham
fuente
Actualizado para Xcode 11+
Las inserciones descritas en mi respuesta original se han trasladado al inspector de tamaño en las versiones más recientes de Xcode. No estoy 100% claro sobre cuándo ocurrió el cambio, pero los lectores deberían revisar el inspector de tamaño si la información del recuadro no se encuentra en el inspector de atributos. A continuación se muestra una muestra de la nueva pantalla de inserción (ubicada en la parte superior del inspector de atributos de tamaño a partir de 11.5).
Respuesta original
No hay nada malo con las otras respuestas, sin embargo, solo quería señalar que el mismo comportamiento se puede lograr visualmente dentro de Xcode usando cero líneas de código. Esta solución es útil si no necesita un valor calculado o si está construyendo con un guión gráfico / xib (de lo contrario, se aplican otras soluciones).
Nota: entiendo que la pregunta del OP es una que requiere código. Solo estoy proporcionando esta respuesta para completar y como una alternativa lógica para aquellos que usan guiones gráficos / xibs.
Para modificar el espaciado en las vistas de imagen, título y contenido de un botón utilizando inserciones de borde, puede seleccionar el botón / control y abrir el inspector de atributos. Desplácese hacia el centro del inspector y busque la sección para inserciones de borde.
También se puede acceder y modificar las inserciones de borde específicas para la vista de título, imagen o contenido.
fuente
No luches contra el sistema. Si sus diseños se vuelven demasiado complejos para administrarlos usando Interface Builder + quizás algún código de configuración simple, haga los diseños manualmente de una manera más simple usando
layoutSubviews
- ¡para eso está! Todo lo demás equivaldrá a hacks.Cree una subclase UIButton y anule su
layoutSubviews
método para alinear su texto e imagen mediante programación. O use algo como https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h para que pueda implementar layoutSubviews usando un bloque.fuente
Subclase UIButton
fuente
Respuesta actualizada de Jesse Crossen para Swift 4 :
Use de esta manera:
fuente
Con este fragmento de código, obtendrás algo como esto
fuente
Extensión UIButton con sintaxis Swift 3+ :
Respuesta original: https://stackoverflow.com/a/7199529/3659227
fuente
Solo un pequeño cambio en la respuesta de Jesse Crossen que hizo que funcionara perfectamente para mí:
en vez de:
He usado esto:
fuente
El uso
button.titleLabel.frame.size.width
funciona bien siempre que la etiqueta sea lo suficientemente corta como para no truncarse. Sin embargo, cuando el texto de la etiqueta se trunca, el posicionamiento no funciona. Tomandofunciona para mí incluso cuando el texto de la etiqueta está truncado.
fuente
Miré las respuestas existentes pero también descubrí que configurar el marco del botón es un primer paso importante.
Aquí hay una función que uso que se encarga de esto:
fuente
O simplemente puede usar esta categoría:
fuente
CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName: button.titleLabel.font}];
Mi caso de uso hizo insertos inmanejables:
Esto es lo que terminé haciendo y estoy bastante feliz con eso:
Cree el botón en el guión gráfico con una imagen de fondo (círculo redondo con desenfoque y color).
Declarar un UIImageView en mi clase:
Crear instancia de vista de imagen en init:
En viewDidLoad agregue una nueva capa al botón para nuestra vista de imagen y configure la alineación del texto:
En el método de hacer clic en el botón, agregue mi imagen de superposición elegida a la vista de imagen, ajústela para que se ajuste a la imagen y céntrela en el botón, pero muévala hacia arriba 15 para que pueda colocar el texto debajo:
Nota: ceilf () es importante para garantizar que esté en un límite de píxeles para la calidad de la imagen.
fuente
Suponiendo que desea que tanto el texto como la imagen estén centrados horizontalmente, imagen arriba del texto: Centre el texto desde el generador de interfaces y agregue un recuadro superior (dejando espacio para la imagen). (deje el recuadro izquierdo a 0). Utilice el generador de interfaces para elegir la imagen: su posición real se establecerá a partir del código, así que no se preocupe de que las cosas no se verán bien en IB. A diferencia de otras respuestas anteriores, esto realmente funciona en todas las versiones de iOS actualmente compatibles (5,6 y 7).
En el código, simplemente descarte el ImageView del botón (configurando la imagen del botón como nulo) después de tomar la imagen (esto también centrará automáticamente el texto, envuelto si es necesario). Luego, cree una instancia de su propio ImageView con el mismo tamaño de cuadro e imagen y colóquelo en el medio.
De esta manera, aún puede elegir la imagen del generador de interfaces (aunque no estará alineada en IB como en el simulador, pero, de nuevo, otras soluciones no son compatibles en todas las versiones compatibles de iOS)
fuente
Estaba luchando para lograr esto porque no podía obtener el tamaño de la imagen y el ancho del texto en el constructor de mi vista. Dos cambios menores en la respuesta de Jesse funcionaron para mí:
Los cambios son:
[NSString sizeWithAttributes]
para obtener el ancho del texto;UIImage
lugar deUIImageView
fuente
Esto funciona bien para mí, para varios botones, con diferente ancho de imagen y diferente longitud de título:
Subclase
UIButton
fuente
Funciona bien para el tamaño del botón 80x80 píxeles.
fuente
Realicé algunos ajustes para alinear la imagen en el centro horizontal:
fuente
¿Es obligatorio usar inserciones de borde? Si no, puede intentar posicionar respecto a la vista central del padre
fuente
Debe mover la imagen hacia la derecha por el ancho del texto. Luego mueva el texto a la izquierda por el ancho de la imagen.
Luego ajuste las inserciones superior e inferior para ajustar el eje Y. Es probable que esto también se pueda hacer mediante programación, pero debe ser constante para el tamaño de su imagen. Mientras que las inserciones del eje X deberán cambiar en función del tamaño de la etiqueta de texto en cada botón.
fuente
Agregue este código en la extensión Swift 4.2
fuente
Solo para tirar mis 2 centavos, esto funcionó para mí:
fuente