如果可以避免,我不想使用子视图。我想要一个带有背景图像,文本和图像的UIButton。现在,当我这样做的时候,图像在文本的左边。背景图像、文本和图像都有不同的高亮状态。


当前回答

在尝试了互联网上的多种解决方案后,我没有达到确切的要求。所以我最终编写了自定义实用程序代码。在将来帮助别人。 在swift 4.2上测试

// This function should be called in/after viewDidAppear to let view render
    func addArrowImageToButton(button: UIButton, arrowImage:UIImage = #imageLiteral(resourceName: "my_image_name") ) {
        let btnSize:CGFloat = 32
        let imageView = UIImageView(image: arrowImage)
        let btnFrame = button.frame
        imageView.frame = CGRect(x: btnFrame.width-btnSize-8, y: btnFrame.height/2 - btnSize/2, width: btnSize, height: btnSize)
        button.addSubview(imageView)
        //Imageview on Top of View
        button.bringSubviewToFront(imageView)
    }

其他回答

我决定不使用标准的按钮图像视图,因为所提出的移动它的解决方案感觉很俗气。这让我获得了想要的美感,并且通过改变约束来重新定位按钮是很直观的:

extension UIButton {
    func addRightIcon(image: UIImage) {
        let imageView = UIImageView(image: image)
        imageView.translatesAutoresizingMaskIntoConstraints = false

        addSubview(imageView)

        let length = CGFloat(15)
        titleEdgeInsets.right += length

        NSLayoutConstraint.activate([
            imageView.leadingAnchor.constraint(equalTo: self.titleLabel!.trailingAnchor, constant: 10),
            imageView.centerYAnchor.constraint(equalTo: self.titleLabel!.centerYAnchor, constant: 0),
            imageView.widthAnchor.constraint(equalToConstant: length),
            imageView.heightAnchor.constraint(equalToConstant: length)
        ])
    }
}

当标题发生变化时,只需更新插图即可。你需要在另一侧用等量的、相反的插页来补偿插页。

[thebutton setTitle:title forState:UIControlStateNormal];
thebutton.titleEdgeInsets = UIEdgeInsetsMake(0, -thebutton.imageView.frame.size.width, 0, thebutton.imageView.frame.size.width);
thebutton.imageEdgeInsets = UIEdgeInsetsMake(0, thebutton.titleLabel.frame.size.width, 0, -thebutton.titleLabel.frame.size.width);

子类化UIButton是完全没有必要的。相反,你可以简单地为图像设置一个高的左插入值,为标题设置一个小的右插入值。就像这样:

button.imageEdgeInsets = UIEdgeInsetsMake(0., button.frame.size.width - (image.size.width + 15.), 0., 0.);
button.titleEdgeInsets = UIEdgeInsetsMake(0., 0., 0., image.size.width);

更新XCODE 9(通过接口生成器)

在Interface Builder中有一个更简单的方法。

选择UIButton并在View Utilities > Semantic中选择这个选项:

就是这样!很好很简单!

可选-第二步:

如果你想调整图像和标题之间的间距,你可以在这里更改图像插入:

这是我在swift 5.2上的工作

let sizeOfTitle: CGFloat = 80
let sizeOfImage: CGFloat = 20
yourButton.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -sizeOfImage , bottom: 0.0, right: sizeOfImage)
yourButton.imageEdgeInsets = UIEdgeInsets(top: 0.0, left: sizeOfTitle, bottom: 0.0, right: -sizeOfTitle)