虽然我来晚了,但我认为我有一些有用的东西要补充。
Kekoa的答案很好,但正如RonLugge所提到的那样,这可能会使按钮不再尊重sizeToFit
,或者更重要的是,当按钮具有内在大小时,可能导致按钮截断其内容。哎呀!
不过,首先需要简要解释一下我认为imageEdgeInsets
和titleEdgeInsets
的工作原理:
有关imageEdgeInsets
的文档部分地表示:
使用此属性可以调整按钮图像的有效绘制矩形的大小和位置。您可以为每个四个插图(上、左、下、右)指定不同的值。正值会缩小或缩进该边缘-将其移动到按钮的中心。负值会扩展或突出该边缘。
我认为编写此文档时想象的是按钮没有标题,只有一个图像。以这种方式考虑更加合理,并且行为方式与UIEdgeInsets
通常相同。基本上,对于正插图,图像的框架(或具有titleEdgeInsets
的标题)向内移动,而对于负插图,则向外移动。
好的,那么怎样?
我来了!以下是默认设置的图像和标题(按钮边框为绿色,只是为了显示其位置):
![Starting image; no space between title and image.](https://istack.dev59.com/9BhvR.webp)
当您想要在图像和标题之间留出间距,而不会使它们中的任何一个被压缩时,您需要设置四个不同的插图,其中两个应用于图像和标题各自。这是因为您不希望更改这些元素框架的大小,而只是它们的位置。当您开始以这种方式思考时,需要对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
等等,你说,当我这样做时,我得到了这个:
![Spacing is good, but the image and title are outside the view's frame.](https://istack.dev59.com/GmVAb.webp)
哦,对了!我忘了,文档警告了我。其中一部分内容如下:
此属性仅用于在布局期间定位图像。按钮不使用此属性确定intrinsicContentSize
和sizeThatFits:
。
但是确实有一个属性可以帮助我们,那就是contentEdgeInsets
。该文档中提到的其中一部分内容如下:
按钮使用此属性确定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
那你得到了什么?
![间距和框架现在是正确的。](https://istack.dev59.com/uTUPc.webp)
对我来说看起来像个赢家。
正在使用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)
}
}
}
intrinsicContentSize
不正确的问题。在这些自动布局的日子里,这非常重要,因为原来的答案已经被接受了。 - Aceyspacing
添加到self.contentEdgeInsets
的四个值中,如下所示:self.contentEdgeInsets = UIEdgeInsetsMake(spacing, spacing + insetAmount, spacing, spacing + insetAmount);
- Erik van der Neutbutton.imageView?.contentMode = .scaleAspectFit
。我为此制作了一个小测试应用程序,您可以在其中进行操作 https://github.com/tomas789/UIButtonEdgeInsets - tomas789