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);
100191 次浏览

It might be best to create a custom UIButton subclass to address this issues in a better manner. Apple might be 'resetting' your settings.

1) button.frame = self.view.bounds;

2)当按钮填满屏幕时,带有负值的 setImageEdgeInsets是疯狂的。重新考虑一下你在这里要做什么?

3) UITextAlignmentCenter is now NSTextAlignmentCenter

4) button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;

In my end, I did this using UIEdgeInsetsMake which the left corner is calculated to make it to the center. I am not sure if there's something really you can make the text at aligned at the center but this works for me. Make sure that you set your left corner to your desired position by calculating the width. e.g. 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];

输出看起来像,

centered text with image

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)

创建按钮并将文本对齐设置为居中,然后添加:

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];

正如我认为的那样,好的解决方案必须对任何文本都有用,而不需要插入的硬编码值(它是关于由玩具公司提供的解决方案)。我使用类似的代码:

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)];

在字符串之后,我还添加了一些字符串,如下所示:

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]];
}

它允许我通过选择一些较小的字体来设置比可用空间更长的标题。我做这个是因为另一种方法:

[buttonView.titleLabel setAdjustsFontSizeToFitWidth:YES];

works not very good, looks like it take the font size for 3-4 points smaller at one step, so some not so long lines become too smaller, than it must to be.

这段代码允许我们将任何文本放在按钮标题空间的正中央。

我在这里看到了很多解决方案,主要集中在设置图标的左侧。我认为添加一个 UIImageView,对齐按钮的左侧和图像,并将它们居中放在一起会更容易。然后,你可以发挥一点抵消,使它看起来不错。

没有密码全是 Interface Builder。

这对我来说很有用,有几个按钮,不同的图像宽度和不同的标题长度:

子类 UIButton,并添加以下方法:

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


}

其中一个窍门是:

  1. 覆盖 titleRectForContentRect使按钮的 titleLabelframe等于按钮的边界
  2. titleLabeltextAlignment调到 .Center
  3. override imageRectForContentRect to specify the origin.x of the button's imageView

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

您可以使用下面的代码在 UIButton 上左对齐图像:-

第一步:

//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;

Step 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];

第三步:

//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];

第四步:

-(void)post_Buying_Needs_BTN_Pressed:(id)sender{
//write your code action here,,
}

谢谢,

我用 Swift-写了一个 UIButton 扩展

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

我会我的按钮文本样式任何我想要的,保持它在中心对齐。 然后在我的按钮上调用这个方法,比如-

myButton.setLeftImage("image_name", 30.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];

如果不行就告诉我。

我的输出enter image description here

此代码使您的按钮图像向左对齐,标题标签移动到按钮中心。B 是按钮:)

b.contentHorizontalAlignment = .Left
let left = (b.frameWidth() - b.titleLabel!.frameWidth()) / 2 - CGRectGetMaxX(b.imageView!.frame)
b.titleEdgeInsets = UIEdgeInsetsMake(0, left, 0, 0)

这个解决方案与 Swift 3一起工作,尊重原始内容和图像边缘插入,同时保持标题标签始终在可用空间的中心,这使得更容易调整边距。

它覆盖 titleRect(forContentRect:)方法并返回正确的帧:

@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


不赞成先前的回答

这在大多数情况下都可以工作,但是一些布局会导致 layoutSubviews在一个无止境的循环中递归地调用自己,所以就是 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)
}
}

这段代码也可以做同样的事情,但是要将图标对准右边:

@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

正确的对齐版本使用 semanticContentAttribute,因此它需要 iOS9 + 。

我知道这个回答有点晚了。 但我有一个非常简单的解决方案,谁想要添加一个图像,使用 UIImageView,在 UIButton 的左侧与居中文本。都是程序控制的

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
}


}

我写了一个 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)
}
}

你可以像这样使用:

yourButton.leftImage(image: yourImage)

瞧!

I've tried almost every solution above and none of them worked as I expected (I had two buttons each with different tittle and with different image width). So I have written my own extension for UIButton, which works flawlessly with different image widths as well as with different titles.

extension UIButton {
func moveImageLeftTextCenter(imagePadding: CGFloat = 30.0, titlePadding: CGFloat = 0.0, minImageTitleDistance: CGFloat = 10.0){
guard let imageViewWidth = imageView?.frame.width else{return}
guard let titleLabelWidth = titleLabel?.intrinsicContentSize.width else{return}
contentHorizontalAlignment = .left


let imageLeftInset = imagePadding - imageViewWidth / 2
var titleLeftInset = (bounds.width - titleLabelWidth) / 2 - imageViewWidth + titlePadding


if titleLeftInset - imageLeftInset < minImageTitleDistance{
titleLeftInset = imageLeftInset + minImageTitleDistance
}


imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imageLeftInset, bottom: 0.0, right: 0.0)
titleEdgeInsets = UIEdgeInsets(top: 0.0, left: titleLeftInset, bottom: 0.0, right: 0.0)
}
}

用法: myButton.moveImageLeftTextCenter()

对于 Swift 4.0,这里有一个可以工作的扩展

extension UIButton {


func leftImage(image: UIImage, renderMode: UIImage.RenderingMode) {
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
self.titleEdgeInsets.left = (self.frame.width/2) - (self.titleLabel?.frame.width ?? 0)
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
}
}

用法:

myButton.rightImage(image: UIImage(named: "image_name")!, renderMode: .alwaysOriginal)
myButton.leftImage(image: UIImage(named: "image_name")!, renderMode: .alwaysOriginal)

renderMode可以是 .alwaysTemplate.alwaysOriginal。同时,myButton应该是 customUIButton

这个扩展的 leftImagerightImage也可以在 UIBarButtonItem中的 UIButton中用于 UINavigationBar(注意: 从 iOS 11开始,导航栏遵循自动布局,因此您需要在 UIBarButtonItem中添加宽度/高度约束)。对于导航栏的使用,请确保遵循苹果推荐的@2x 和@3x 图像大小(即50x50,75x75) ,并且在 iPhone 6,7,8,6s,7s,8s,Plus 变体和 iPhone x 上具有更好的可访问性。 UIBarButton的宽度和高度可以是高度 -25和宽度 -55(或者不管你的应用程序需要什么,这些数字是一些基本的数字,在大多数情况下应该可以工作)。


更新 : 在 Swift 4.2中,UIImageRenderingMode被重命名为 UIImage.RenderingMode

extension UIButton {
func leftImage(image: UIImage, renderMode: UIImage.RenderingMode) {
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: UIImage.RenderingMode){
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
}
}

此解决方案可以使用扩展应用。不需要子类化。

Warning: this must be called every time the text/image is updated.

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)

以下扩展适用于 Swift 4.2中的我

func leftImage(image: UIImage, padding: CGFloat, renderMode: UIImage.RenderingMode) {
self.setImage(image.withRenderingMode(renderMode), for: .normal)
contentHorizontalAlignment = .left
let availableSpace = bounds.inset(by: 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)
imageEdgeInsets = UIEdgeInsets(top: 0, left: padding, bottom: 0, right: 0)
}


func rightImage(image: UIImage, padding: CGFloat, renderMode: UIImage.RenderingMode){
self.setImage(image.withRenderingMode(renderMode), for: .normal)
semanticContentAttribute = .forceRightToLeft
contentHorizontalAlignment = .right
let availableSpace = bounds.inset(by: 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)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: padding)
}

大部分答案我都试过了,但都没有成功。我大部分时间都是蓝色的,或者标题不在中间。使用代码从几个答案和写这个扩展,工程喜欢一个魅力。

迅捷4.2:

import UIKit


extension UIButton {
func moveImageLeftTextCenter(image : UIImage, imagePadding: CGFloat, renderingMode: UIImage.RenderingMode){
self.setImage(image.withRenderingMode(renderingMode), for: .normal)
guard let imageViewWidth = self.imageView?.frame.width else{return}
guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
self.contentHorizontalAlignment = .left
let imageLeft = imagePadding - imageViewWidth / 2
let titleLeft = (bounds.width - titleLabelWidth) / 2 - imageViewWidth
imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imageLeft, bottom: 0.0, right: 0.0)
titleEdgeInsets = UIEdgeInsets(top: 0.0, left: titleLeft , bottom: 0.0, right: 0.0)
}
}

希望对某些人有帮助!

可以通过使用 UIButton 的自定义类来实现这一点。

class CustomButton: UIButton {


var imageV = UIImageView()
var titleV = UILabel()


override func awakeFromNib() {


self.imageView?.isHidden = true
self.titleLabel?.isHidden = true


imageV.frame = CGRect(x: 0, y: 0, width: 40, height: self.bounds.height)
imageV.contentMode = .scaleAspectFit


titleV.frame = CGRect(x: 40, y: 0, width: self.bounds.width - 40, height: self.bounds.height)
titleV.font = self.titleLabel?.font
titleV.textAlignment = .center


self.addSubview(imageV)
self.addSubview(titleV)


imageV.image = self.imageView?.image; titleV.text = self.titleLabel?.text


imageV.translatesAutoresizingMaskIntoConstraints = false
imageV.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
imageV.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
imageV.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
imageV.trailingAnchor.constraint(equalTo: titleV.leadingAnchor, constant: 0).isActive = true
imageV.widthAnchor.constraint(equalToConstant: 40).isActive = true


titleV.translatesAutoresizingMaskIntoConstraints = false
titleV.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
titleV.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
titleV.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
}
}

然后你可以像这样设置图片和文本。

button.imageV.image = myImage
button.titleV.text = myText

结果

enter image description here

我的 SWIFT 5.2溶液。

You have to subclass UIButton class. No need to change the content horizontal alignment like others did in other answers, keep it to "center" (.center). The title will be automatically centered, while the override of imageRect() will do the trick for the image.

您必须做的第一件事情是在故事板的身份检查器部分中为您的按钮分配 CustomButton 类。 然后,可以在属性检查器部分将“ alignImageToLeft”切换为 ON 或 OFF (默认为 OFF)。

class CustomButton : UIButton {


@IBInspectable var alignImageToLeft : Bool = false


override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
if(alignImageToLeft){
let imageRect = super.imageRect(forContentRect: contentRect)
let offset = contentRect.minX - imageRect.minX
return imageRect.offsetBy(dx: offset, dy: 0.0)
}
return super.imageRect(forContentRect: contentRect)
}
}

快速版:

var button = UIButton()


newGameButton.setTitle("Новая игра", for: .normal)
newGameButton.setImage(UIImage(named: "energi"), for: .normal)
newGameButton.backgroundColor = .blue
newGameButton.imageEdgeInsets.left = -50

enter image description here

您可能忘记了 UIEdgeInsets,只是在 UIButton 子类中覆盖 layoutSubviews ()中的框架。

要使 titleLable 居中,只需通过 super.bound. midX 和 titleLabel.frame.midX 之间的差异向 titleLabel 框架添加水平偏移量即可

   override func layoutSubviews() {
super.layoutSubviews()
       

if let label = titleLabel {
label.frame = label.frame.offsetBy(dx: super.bounds.midX -
label.frame.midX , dy: 0)
}


// Available space to the left of the titleLabel is simply:
let leftAvailableWidth = label.frame.minX


imageView?.frame = CGRect(x: 0, y: 0, width: <Some width smaller than leftAvailableWidth>, height: super.bound.height)
}

这适用于不同按钮文本大小的我。

准确的按钮文本宽度的关键是获取 intrinsicContentSize。因为我使用了按钮宽度的自动布局,所以我不得不从 viewDidAppear 而不是 viewDidLoad 运行这段代码,这样按钮就已经绘制好了,因此按钮帧大小也就准确了。

private func calculateAccountButtonImageViewOffset(button: UIButton, padding: CGFloat = 30.0) -> CGFloat {
let buttonWidth = button.frame.width
let textWidth = button.titleLabel?.intrinsicContentSize.width ?? 0
let imageViewWidth = button.imageView?.frame.size.width ?? 0
let offsetToLeftButtonEdge = buttonWidth - textWidth - imageViewWidth
return offsetToLeftButtonEdge - padding
}

用法:

let imageViewOffset = calculateAccountButtonImageViewOffset(button: button)
button.imageEdgeInsets = UIEdgeInsets(top: 0.0, left: 0, bottom: 0.0, right: imageViewOffset)

The button title can be offset as desired with Title Insets on IB: enter image description here

@trishcode answer worked for me. I am just using it with an extension of the UIButton.

密码如下:

extension UIButton {
func centerImageLeft(padding: CGFloat = 30.0){
let buttonWidth = self.frame.width
let textWidth = self.titleLabel?.intrinsicContentSize.width ?? 0
let imageViewWidth = self.imageView?.frame.size.width ?? 0
let offsetToLeftButtonEdge = buttonWidth - textWidth - imageViewWidth
let offset = offsetToLeftButtonEdge - padding
self.imageEdgeInsets = UIEdgeInsets(top: 0.0, left: 0, bottom: 0.0, right: offset)
}
}

You can then call it like this in the viewDidAppear Method:

button.centerImageLeft()