在 UIButton 上左对齐图像并居中文本

79

我看到了有关右对齐的帖子,但我无法让左对齐起作用。 我希望按钮占据屏幕的宽度,图像位于左侧,标题/文本位于中心。

以下代码不起作用(至少不可靠):

    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);
27个回答

3

我用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)

这将导致我的图像与左边框有一些填充的左对齐。

你有一个名为'padding'的参数和在函数中实例化的值叫做'padding'。这将覆盖参数函数,应在使用之前进行优化。 - Jstngoulet

3

1) 按钮的位置赋值为 self.view.bounds

2) 在按钮填充整个屏幕时,使用负值设置 setImageEdgeInsets 是不可取的。请重新思考你要做什么。

3) UITextAlignmentCenter 现在应该改为 NSTextAlignmentCenter

4) 将按钮的水平对齐方式设置为 UIControlContentHorizontalAlignmentLeft


2

一个技巧是:

  1. Override titleRectForContentRect to make the button's titleLabel's frame equal to the button's bounds
  2. Set the titleLabel's textAlignment to .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")
        }
    }
    

2
我看到很多解决方案都是将图标设置到左侧。我认为更简单的方法是添加一个UIImageView,将按钮和图片的左侧对齐并一起居中。然后你可以稍微调整偏移量使其看起来更好。
没有代码,全部在Interface Builder中完成。

是的,但那个图像会响应用户的触摸,比如改变颜色吗? - vedrano
你可以在所有的图片上使用色调,但默认情况下它是关闭的:https://dev59.com/VWEh5IYBdhLWcg3wpE7w - Lucas van Dongen
我猜你是对的。因此,您建议应用程序应覆盖setSelected()方法并手动维护图像外观(而不是默认行为)。 - vedrano

2

我知道这个答案有点晚了。 但是我有一个非常简单的解决方案,适用于想要在UIButton的左侧使用UIImageView添加图片并居中文本的人。全部通过编程实现。

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
    }

}

2

以下扩展在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)
}

2
我的SWIFT 5.2解决方案。
您需要子类化UIButton类。不需要像其他答案中那样更改内容的水平对齐方式,将其保持为“center”(.center)。标题将自动居中,而imageRect()的覆盖将处理图像。
首先,您需要在Storyboard的Identity Inspector部分将CustomButton类分配给按钮。 然后,您可以在Attribute Inspector部分切换“alignImageToLeft”以打开或关闭(默认为关闭)。
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)
    }
}

1

这个解决方案可以通过扩展来实现,无需子类化。

警告:每次更新文本/图像时都必须调用此方法。

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)

1
这段代码使你的按钮图像左对齐,标题标签移动到按钮中心。b是按钮 :)
b.contentHorizontalAlignment = .Left
let left = (b.frameWidth() - b.titleLabel!.frameWidth()) / 2 - CGRectGetMaxX(b.imageView!.frame)
b.titleEdgeInsets = UIEdgeInsetsMake(0, left, 0, 0)

1
您可以使用以下代码将图像左对齐到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;

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

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

感谢。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接