UIButton:如何使用imageEdgeInsets将图像和文本居中?

如果我只在按钮中放置一个图像,然后将imageEdgeInsets设置为更靠近顶部,则图像将居中,并且所有工作都将按预期进行:


[button setImage:image forState:UIControlStateNormal];

[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, 0.0)];

如果我仅在按钮中放置文本,然后将titleEdgeInsets设置为更靠近底部,则文本将居中,并且一切正常


[button setTitle:title forState:UIControlStateNormal];

[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, -30, 0.0)];

但是,如果我将4行放在一起,则文本会干扰图像,并且都失去中心对齐。


我所有的图像都有30像素的宽度,如果我在setSettletleEdgeInsets的UIEdgeInsetMake的左侧参数中放了30个像素,则文本将再次居中。问题在于图像永远不会居中,因为它似乎取决于button.titleLabel的大小。我已经尝试过使用按钮大小,图像大小,titleLabel大小进行许多计算,并且永远都无法完美地居中。


有人已经遇到了同样的问题吗?


饮歌长啸
浏览 500回答 3
3回答

呼如林

对于它的价值,这是一种将图像居中放置在文本上方而不使用任何幻数的通用解决方案。请注意,以下代码已过时,您可能应该使用以下更新版本之一:// the space between the image and textCGFloat spacing = 6.0;// lower the text and push it left so it appears centered //  below the imageCGSize imageSize = button.imageView.frame.size;button.titleEdgeInsets = UIEdgeInsetsMake(  0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);// raise the image and push it right so it appears centered//  above the textCGSize titleSize = button.titleLabel.frame.size;button.imageEdgeInsets = UIEdgeInsetsMake(  - (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);以下版本包含以下注释中推荐的支持iOS 7+的更改。我还没有亲自测试过此代码,因此不知道它的运行效果如何,或者如果在以前的iOS版本中使用,它是否会损坏。// the space between the image and textCGFloat spacing = 6.0;// lower the text and push it left so it appears centered //  below the imageCGSize imageSize = button.imageView.image.size;button.titleEdgeInsets = UIEdgeInsetsMake(  0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);// raise the image and push it right so it appears centered//  above the textCGSize titleSize = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}];button.imageEdgeInsets = UIEdgeInsetsMake(  - (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);// increase the content height to avoid clippingCGFloat edgeOffset = fabsf(titleSize.height - imageSize.height) / 2.0;button.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0);Swift 5.0版本extension UIButton {  func alignVertical(spacing: CGFloat = 6.0) {    guard let imageSize = imageView?.image?.size,      let text = titleLabel?.text,      let font = titleLabel?.font    else { return }    titleEdgeInsets = UIEdgeInsets(      top: 0.0,      left: -imageSize.width,      bottom: -(imageSize.height + spacing),      right: 0.0    )    let titleSize = text.size(withAttributes: [.font: font])    imageEdgeInsets = UIEdgeInsets(      top: -(titleSize.height + spacing),      left: 0.0,      bottom: 0.0, right: -titleSize.width    )    let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0    contentEdgeInsets = UIEdgeInsets(      top: edgeOffset,      left: 0.0,      bottom: edgeOffset,      right: 0.0    )  }}

慕莱坞森

找到了。首先,配置titleLabel(由于样式,例如,粗体,斜体等)的文本。然后,setTitleEdgeInsets考虑图像的宽度:[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];[button setTitle:title forState:UIControlStateNormal];[button.titleLabel setFont:[UIFont boldSystemFontOfSize:10.0]];// Left inset is the negative of image width.[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, -image.size.width, -25.0, 0.0)]; 之后,请setTitleEdgeInsets考虑文本边界的宽度:[button setImage:image forState:UIControlStateNormal];// Right inset is the negative of text bounds width.[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, -button.titleLabel.bounds.size.width)];现在,图像和文本将居中(在此示例中,图像显示在文本上方)。

有只小跳蛙

您可以使用此Swift扩展来做到这一点,该扩展部分基于Jesse Crossen的回答:extension UIButton {  func centerLabelVerticallyWithPadding(spacing:CGFloat) {    // update positioning of image and title    let imageSize = self.imageView.frame.size    self.titleEdgeInsets = UIEdgeInsets(top:0,                                        left:-imageSize.width,                                        bottom:-(imageSize.height + spacing),                                        right:0)    let titleSize = self.titleLabel.frame.size    self.imageEdgeInsets = UIEdgeInsets(top:-(titleSize.height + spacing),                                        left:0,                                        bottom: 0,                                        right:-titleSize.width)    // reset contentInset, so intrinsicContentSize() is still accurate    let trueContentSize = CGRectUnion(self.titleLabel.frame, self.imageView.frame).size    let oldContentSize = self.intrinsicContentSize()    let heightDelta = trueContentSize.height - oldContentSize.height    let widthDelta = trueContentSize.width - oldContentSize.width    self.contentEdgeInsets = UIEdgeInsets(top:heightDelta/2.0,                                          left:widthDelta/2.0,                                          bottom:heightDelta/2.0,                                          right:widthDelta/2.0)  }}这定义了一个centerLabelVerticallyWithPadding适当设置标题和图像插图的函数。它还设置contentEdgeInsets,我认为这是确保intrinsicContentSize仍然正确运行所必需的,这将需要使用“自动布局”。我相信从子类上继承UIButton的所有解决方案在技术上都是非法的,因为您不应该将UIKit控件子类化。即,从理论上讲,它们可能会在将来的版本中中断。
打开App,查看更多内容
随时随地看视频慕课网APP