Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Left-align image and center text on UIButton

I've seen posts regarding right alignment but I can't get left-alignment to work. I want the button to take up the width of the screen, with the image on the left and the title/text in the center.

This does not work (at least reliably):

    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); 
like image 286
user1007721 Avatar asked Jun 08 '12 19:06

user1007721


1 Answers

This solution works with Swift 3 and respects original content and image edge insets while keeping the title label always centered in the available space, which makes much easier adjusting margins.

It overrides titleRect(forContentRect:) method and returns the correct frame:

@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)     } } 

The following insets:

enter image description here

Would result in this:

enter image description here


Deprecated previous answer

This works in most scenarios, but some layouts cause layoutSubviews to recursively call itself in an endless loop, so use with caution.

@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)     } } 

This code would do the same but aligning the icon to the right edge:

@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)     } } 

enter image description here

The right allignment version uses semanticContentAttribute so it requires iOS 9+.

like image 70
redent84 Avatar answered Sep 16 '22 17:09

redent84