ios - Imagen de alineación izquierda y texto central en UIButton
uiimage (18)
He visto publicaciones relacionadas con la alineación correcta, pero no puedo hacer que la alineación a la izquierda funcione. Quiero que el botón ocupe el ancho de la pantalla, con la imagen a la izquierda y el título / texto en el centro.
Esto no funciona (al menos confiablemente):
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setImageEdgeInsets:UIEdgeInsetsMake(0, -60.0, 0, 0)];
button.frame = CGRectMake((self.view.frame.size.width - w ) / 2, self.view.frame.size.height - 140.0, self.view.frame.size.width - 10.0, 40.0);
1) button.frame = self.view.bounds;
2) setImageEdgeInsets
con valores negativos, cuando el botón llena la pantalla, es una locura. Reconsidere lo que está tratando de hacer aquí?
3) UITextAlignmentCenter
ahora es NSTextAlignmentCenter
4) button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
Como creo, la buena solución debe ser útil para cualquier texto, sin valores codificados para las inserciones (se trata de la solución proporcionada por toytoy). Yo uso el código similar a esto:
NSString *sometitle = @"blabla button title";
NSString *someimage = @"blablaimage";
UIImage *image = [[UIImage imageNamed:someimage];
int buttonWidth = A;
int buttonHeight = B;
int imageWidth =image.size.width;
int imageHeight = image.size.height;
int titleWidth = buttonWidth - imageWidth;
// create button and set image and title
buttonView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, buttonWidth, buttonHeight)];
[buttonView setImage:image forState:UIControlStateNormal];
[buttonView setTitle:sometitle forState:UIControlStateNormal];
// make button all content to be left aligned
[buttonView setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
// set title font
[buttonView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:14]];
// calculate font text width with selected font
CGSize stringBoundingBox = [number sizeWithFont:[buttonView.titleLabel font]];
// make title inset with some value from left
// it place the title right on the center of space for the title
int titleLeft = (titleWidth - stringBoundingBox.width) / 2;
[buttonView setTitleEdgeInsets:UIEdgeInsetsMake(0, titleLeft, 0, 0)];
Después de la cadena con stringBoundingBox init también agrego algunas cadenas como esta:
if (stringBoundingBox.width > titleWidth)
{
[_backgroundView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:13]];
stringBoundingBox = [number sizeWithFont:[_backgroundView.titleLabel font]];
}
if (stringBoundingBox.width > titleWidth)
{
[_backgroundView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:12]];
stringBoundingBox = [number sizeWithFont:[_backgroundView.titleLabel font]];
}
me permite configurar los títulos más largos que el espacio disponible, seleccionando algunas fuentes más pequeñas. Lo hago por otra forma de esto:
[buttonView.titleLabel setAdjustsFontSizeToFitWidth:YES];
no funciona muy bien, parece que toma el tamaño de fuente de 3-4 puntos más pequeño en un paso, por lo que algunas líneas no demasiado largas se vuelven demasiado pequeñas, de lo que debe ser.
Este código nos permite colocar cualquier texto en el espacio del título del botón exactamente en el centro.
Crea tu botón y establece la alineación del texto al centro, luego agrega:
UIImage *image = [UIImage imageNamed:@"..."];
CGSize imageSize = image.size;
CGFloat offsetY = floor((self.layer.bounds.size.height - imageSize.height) / 2.0);
CALayer *imageLayer = [CALayer layer];
imageLayer.contents = (__bridge id) image.CGImage;
imageLayer.contentsGravity = kCAGravityBottom;
imageLayer.contentsScale = [UIScreen mainScreen].scale;
imageLayer.frame = CGRectMake(offsetY, offsetY, imageSize.width, imageSize.height);
[self.layer addSublayer:imageLayer];
En mi caso, lo hice usando UIEdgeInsetsMake, que la esquina izquierda se calcula para llegar al centro. No estoy seguro de si hay algo realmente que pueda hacer que el texto esté alineado en el centro, pero esto funciona para mí. Asegúrese de establecer su esquina izquierda en la posición deseada calculando el ancho. por ejemplo, UIEdgeInsetsMake(0.0f, 42.0f, 0.0f, 0.0f)
UIButton *scanBarCodeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
scanBarCodeButton.frame = CGRectMake(center, 10.0f, fieldWidth, 40.0f);
[scanBarCodeButton setImage:[UIImage imageNamed:@"BarCodeIcon.png"] forState:UIControlStateNormal];
[scanBarCodeButton setTitle:@"Scan the Barcode" forState:UIControlStateNormal];
scanBarCodeButton.titleEdgeInsets = UIEdgeInsetsMake(0.0f, 42.0f, 0.0f, 0.0f);
[scanBarCodeButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[scanBarCodeButton addTarget:self action:@selector(scanBarCode:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:scanBarCodeButton];
La salida se ve así,
texto centrado con imagen http://i43.tinypic.com/33mbxxi.png
En Swift :
var scanBarCodeButton: UIButton = UIButton(type: .roundedRect)
scanBarCodeButton.frame = CGRectMake(center, 10.0, fieldWidth, 40.0)
scanBarCodeButton.setImage(UIImage(named: "BarCodeIcon.png"), for: UIControlStateNormal)
scanBarCodeButton.setTitle("Scan the Barcode", for: UIControlStateNormal)
scanBarCodeButton.titleEdgeInsets = UIEdgeInsetsMake(0.0, 42.0, 0.0, 0.0)
scanBarCodeButton.contentHorizontalAlignment = .left
scanBarCodeButton.addTarget(self, action: "scanBarCode:", for: UIControlEventTouchUpInside)
self.view.addSubview(scanBarCodeButton)
Escribí una extensión UIButton en swift -
extension UIButton {
func setLeftImage(imageName:String, padding:CGFloat) {
//Set left image
let image = UIImage(named: imageName)
self.setImage(image, forState: .Normal)
//Calculate and set image inset to keep it left aligned
let imageWidth = image?.size.width
let textWidth = self.titleLabel?.intrinsicContentSize().width
let buttonWidth = CGRectGetWidth(self.bounds)
let padding:CGFloat = 30.0
let rightInset = buttonWidth - imageWidth! - textWidth! - padding
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: rightInset)
}
}
Personalizaría el texto de mi botón de la forma que quisiera, manteniéndolo en alineación central. Entonces llamaría a este método en mi botón como ...
myButton.setLeftImage("image_name", 30.0)
Esto daría como resultado que mi imagen quedara alineada con algún relleno del borde izquierdo.
Escribí una extensión UIButton.
extension UIButton {
/// Add image on left view
func leftImage(image: UIImage) {
self.setImage(image, for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width)
}
}
Y podrías usar esto:
yourButton.leftImage(image: yourImage)
Voila!
Esta solución funciona con Swift 3 y respeta el contenido original y las opciones de bordes de la imagen, manteniendo la etiqueta del título siempre centrada en el espacio disponible, lo que hace que sea mucho más fácil ajustar los márgenes.
titleRect(forContentRect:)
método titleRect(forContentRect:)
y devuelve el fotograma correcto:
@IBDesignable
class LeftAlignedIconButton: UIButton {
override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
let titleRect = super.titleRect(forContentRect: contentRect)
let imageSize = currentImage?.size ?? .zero
let availableWidth = contentRect.width - imageEdgeInsets.right - imageSize.width - titleRect.width
return titleRect.offsetBy(dx: round(availableWidth / 2), dy: 0)
}
}
Las siguientes inserciones:
Daría lugar a esto:
Respuesta anterior obsoleta
Esto funciona en la mayoría de los escenarios, pero algunos diseños hacen que layoutSubviews
llame layoutSubviews
a sí mismo en un bucle infinito, por lo que debe usarse con precaución .
@IBDesignable
class LeftAlignedIconButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
contentHorizontalAlignment = .left
let availableSpace = UIEdgeInsetsInsetRect(bounds, contentEdgeInsets)
let availableWidth = availableSpace.width - imageEdgeInsets.right - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: availableWidth / 2, bottom: 0, right: 0)
}
}
Este código haría lo mismo pero alineando el ícono al borde derecho:
@IBDesignable
class RightAlignedIconButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
semanticContentAttribute = .forceRightToLeft
contentHorizontalAlignment = .right
let availableSpace = UIEdgeInsetsInsetRect(bounds, contentEdgeInsets)
let availableWidth = availableSpace.width - imageEdgeInsets.left - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: availableWidth / 2)
}
}
La versión de alineación correcta usa semanticContentAttribute
por lo que requiere iOS 9+.
Esta solución se puede aplicar usando una extensión. No hay necesidad de subclases.
Advertencia: debe invocarse cada vez que se actualiza el texto / imagen.
let width = frame.width
guard let imageWidth = imageView?.frame.width, let labelWidth = titleLabel?.frame.width else {
return
}
titleEdgeInsets = UIEdgeInsets(top: 0, left: (width - labelWidth)/2.0 - imageWidth, bottom: 0, right: 0)
Esto funciona bien para mí, para varios botones, con diferente ancho de imagen y diferente longitud de título:
Subclase UIButton
y agregue el siguiente método:
override func layoutSubviews() {
super.layoutSubviews()
if let image = imageView?.image {
let margin = 30 - image.size.width / 2
let titleRect = titleRectForContentRect(bounds)
let titleOffset = (bounds.width - titleRect.width - image.size.width - margin) / 2
contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
imageEdgeInsets = UIEdgeInsetsMake(0, margin, 0, 0)
titleEdgeInsets = UIEdgeInsetsMake(0, (bounds.width - titleRect.width - image.size.width - margin) / 2, 0, 0)
}
}
He intentado casi todas las soluciones anteriores y ninguna de ellas funcionó como esperaba (tenía dos botones, cada uno con una tilde diferente y con un ancho de imagen diferente). Así que escribí mi propia extensión para UIButton, que funciona sin problemas con diferentes anchos de imagen y con diferentes títulos.
extension UIButton {
func moveImageLeftTextCenter(imagePadding: CGFloat = 30.0){
guard let imageViewWidth = self.imageView?.frame.width else{return}
guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
self.contentHorizontalAlignment = .left
imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imagePadding - imageViewWidth / 2, bottom: 0.0, right: 0.0)
titleEdgeInsets = UIEdgeInsets(top: 0.0, left: (bounds.width - titleLabelWidth) / 2 - imageViewWidth, bottom: 0.0, right: 0.0)
}
}
Uso: myButton.moveImageLeftTextCenter()
Para Swift 4, aquí hay una extensión que funciona-
extension UIButton {
func leftImage(image: UIImage, renderMode: UIImageRenderingMode) {
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width / 2)
self.contentHorizontalAlignment = .left
self.imageView?.contentMode = .scaleAspectFit
}
func rightImage(image: UIImage, renderMode: UIImageRenderingMode){
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left:image.size.width / 2, bottom: 0, right: 0)
self.contentHorizontalAlignment = .right
self.imageView?.contentMode = .scaleAspectFit
}
}
Uso:
myButton.rightImage(image: UIImage(named: "image_name")!, renderMode: .alwaysOriginal)
myButton.leftImage(image: UIImage(named: "image_name")!, renderMode: .alwaysOriginal)
renderMode
puede ser .alwaysTemplate
o .alwaysOriginal
. Además, myButton
debería ser un UIButton
tipo custom
.
Los leftImage
y rightImage
esta extensión también se pueden usar en UIButton
en UIBarButtonItem
para UINavigationBar
(Nota: a partir de iOS 11, la barra de navegación sigue al diseño automático, por lo que deberá agregar restricciones de ancho / alto al UIBarButtonItem
). Para usar en la barra de navegación, asegúrese de seguir los tamaños de imagen @ 2x y @ 3x recomendados por Apple (es decir, 50x50, 75x75) y tener un mejor acceso en iPhone 6, 7, 8, 6, 7, 8, las variantes Plus y iPhone x el ancho y alto del UIBarButton
podría ser alto - 25 y ancho - 55 (o lo que requiera su aplicación, estos números son algunos números básicos que deberían funcionar para la mayoría de los casos).
Podría ser mejor crear una subclase UIButton personalizada para abordar estos problemas de una mejor manera. Apple podría estar "restableciendo" tu configuración.
Puede usar el siguiente código para alinear la imagen a la izquierda en UIButton: -
Paso 1:
//create your UIButton
UIButton *post_bNeeds_BTN= [UIButton buttonWithType:UIButtonTypeRoundedRect];
post_bNeeds_BTN.frame= CGRectMake(160 ,5 ,150 ,40);
[post_bNeeds_BTN addTarget:self action:@selector(post_Buying_Needs_BTN_Pressed:) forControlEvents:UIControlEventTouchUpInside];
[post_bNeeds_BTN setBackgroundColor:[UIColor colorWithRed:243/255.0 green:131/255.0 blue:26/255.0 alpha:1.0f]];//230
[self.view addSubview:post_bNeeds_BTN];
post_bNeeds_BTN.autoresizingMask= UIViewAutoresizingFlexibleWidth;
Paso 2:
//Add UIImageView on right side the button
UIImageView *bNeedsIVw= [[UIImageView alloc] initWithFrame:CGRectMake(5,5,30,30)];
bNeedsIVw.image= [UIImage imageNamed:@"postRequir_30.png"];
bNeedsIVw.image= [bNeedsIVw.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
bNeedsIVw.tintColor= [UIColor whiteColor];
[post_bNeeds_BTN addSubview:bNeedsIVw];
Paso 3:
//also set UILable on UIButton
UILabel *bNeedsLbl= [[UILabel alloc] initWithFrame:CGRectMake(40 ,0 ,post_Prod_BTN.frame.size.width-40 ,post_Prod_BTN.frame.size.height)];
bNeedsLbl.text= @"Requirements";
bNeedsLbl.font= [UIFont systemFontOfSize:16];
bNeedsLbl.textColor= [UIColor whiteColor];
bNeedsLbl.textAlignment= NSTextAlignmentLeft;
[post_bNeeds_BTN addSubview:bNeedsLbl];
Etapa 4:
-(void)post_Buying_Needs_BTN_Pressed:(id)sender{
//write your code action here,,
}
Gracias,
Sé que esta respuesta es un poco tarde. Pero tengo una solución muy simple para las personas que desean agregar una imagen, usando UIImageView, en el lado izquierdo de un UIButton con texto centrado. Todo programáticamente
class RandomVC: UIViewController{
var imageDemo: UIImageView = {
let img = UIImageView()
img.translatesAutoresizingMaskIntoConstraints = false
img.image = UIImage(named: "someImgFromAssets")
return img
}()
lazy var someButton: UIButton = { //lazy var: so button can have access to self class
let button = UIButton(type: .system)
button.setTitle("This is your title", for: UIControlState.normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitleColor(UIColor.white, for: UIControlState.normal)
button.addTarget(self, action: #selector(handleButtonClick), for: .touchUpInside) //make sure you write function "handleButtonClick" inside your class
button.titleLabel?.textAlignment = .center
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubView(someButton)
someButton.addSubview(imageDemo)
imageDemo.centerYAnchor.constraint(equalTo: someButton.centerYAnchor).isActive = true
imageDemo.leftAnchor.constraint(equalTo: someButton.leftAnchor, constant: 10).isActive = true
imageDemo.heightAnchor.constraint(equalToConstant: 25).isActive = true
imageDemo.widthAnchor.constraint(equalToConstant: 25).isActive = true
}
}
Un truco es:
- Reemplazar
titleRectForContentRect
para que eltitleLabel
deltitleLabel
igual a los límites del botón - Establezca la
titleLabel
detextAlignment
de.Center
en.Center
anula
imageRectForContentRect
para especificar elorigin.x
delorigin.x
del botónimport UIKit class ButtonWithLeftAlignedImageAndCenteredText: UIButton { override init(frame: CGRect) { super.init(frame: frame) titleLabel?.textAlignment = .Center } override func imageRectForContentRect(contentRect: CGRect) -> CGRect { var imageFrame = super.imageRectForContentRect(contentRect) imageFrame.origin.x = 20 //offset from left edge return imageFrame } override func titleRectForContentRect(contentRect:CGRect) -> CGRect { var titleFrame = super.titleRectForContentRect(contentRect) titleFrame = self.bounds return titleFrame } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
Veo muchas soluciones aquí que se enfocan en configurar el ícono a la izquierda. Creo que es mucho más fácil simplemente agregar un UIImageView, alinear los lados izquierdos del botón y la imagen y centrarlos también. Entonces puedes jugar un poco con el desplazamiento para que se vea bien.
Sin código, todo en Interface Builder.
este código hace que la imagen de su botón se alinee a la izquierda, y la etiqueta del título se mueve al centro del botón. b es el botón :)
b.contentHorizontalAlignment = .Left
let left = (b.frameWidth() - b.titleLabel!.frameWidth()) / 2 - CGRectGetMaxX(b.imageView!.frame)
b.titleEdgeInsets = UIEdgeInsetsMake(0, left, 0, 0)
[self.button setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
[self.button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, self.button.center.x/2 , 0.0, 0.0)];
[self.button setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
Avíseme si no está funcionando.