我参加这个聚会有点晚了,但我想我有一些有用的东西要补充。
Kekoa 的回答很好,但是,正如 RonLugge 所提到的,它可以使按钮不再尊重 sizeToFit,或者更重要的是,可以导致按钮在固有大小时剪切其内容。哎呀!
首先,
我认为imageEdgeInsets 和titleEdgeInsets 工作原理的简要说明:
docs for imageEdgeInsets 部分内容如下:
使用此属性调整按钮图像的有效绘图矩形的大小和位置。您可以为四个插图(上、左、下、右)中的每一个指定不同的值。正值会缩小或插入该边缘 - 将其移近按钮的中心。负值会扩展或扩展该边缘。
我相信这个文档是在想象按钮没有标题,只有图像的情况下编写的。以这种方式思考更有意义,并且表现出UIEdgeInsets 通常的行为方式。基本上,图像的框架(或标题,titleEdgeInsets)向内移动以获取正插图,向外移动以获取负插图。
好的,那又怎样?
我来了!这是你默认的,设置图像和标题(按钮边框是绿色的,只是为了显示它的位置):
当您希望图像和标题之间有间距时,不会导致任何一个被压碎,您需要设置四个不同的插图,每个图像和标题两个。那是因为您不想更改这些元素框架的 大小,而只想更改它们的位置。当您开始以这种方式思考时,对 Kekoa 优秀类别的必要更改就变得清晰了:
@implementation UIButton(ImageTitleCentering)
- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing {
CGFloat insetAmount = spacing / 2.0;
self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount);
self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount);
}
@end
但是等等,你说,当我这样做时,我明白了:
哦,是的!我忘了,the docs 警告过我这一点。他们说,部分:
此属性仅用于在布局期间定位图像。该按钮不使用该属性来确定intrinsicContentSize 和sizeThatFits:。
但是有一个 属性可以提供帮助,那就是contentEdgeInsets。 The docs 部分原因是:
按钮使用此属性来确定intrinsicContentSize 和sizeThatFits:。
听起来不错。所以让我们再次调整类别:
@implementation UIButton(ImageTitleCentering)
- (void)centerButtonAndImageWithSpacing:(CGFloat)spacing {
CGFloat insetAmount = spacing / 2.0;
self.imageEdgeInsets = UIEdgeInsetsMake(0, -insetAmount, 0, insetAmount);
self.titleEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, -insetAmount);
self.contentEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, insetAmount);
}
@end
你得到了什么?
在我看来是个赢家。
在 Swift 中工作并且根本不想做任何思考?这是 Swift 中扩展的最终版本:
extension UIButton {
func centerTextAndImage(spacing: CGFloat) {
let insetAmount = spacing / 2
let isRTL = UIView.userInterfaceLayoutDirection(for: semanticContentAttribute) == .rightToLeft
if isRTL {
imageEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: -insetAmount)
titleEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount, bottom: 0, right: insetAmount)
contentEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount, bottom: 0, right: -insetAmount)
} else {
imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount, bottom: 0, right: insetAmount)
titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: -insetAmount)
contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
}
}
}