ios uiimage uibutton

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:

  1. Reemplazar titleRectForContentRect para que el titleLabel del titleLabel igual a los límites del botón
  2. Establezca la titleLabel de textAlignment de .Center en .Center
  3. anula imageRectForContentRect para especificar el origin.x del origin.x del botón

    import 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.

Mi salida