ios - UIButton:如何使用 imageEdgeInsets 和 titleEdgeInsets 使图像和文本居中?

标签 ios objective-c uibutton

如果我只在按钮中放置一个图像并将 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 像素宽度,如果我在 UIEdgeInsetMake 的左侧参数中为 setTitleEdgeInsets 设置 30,则文本再次居中。问题是图像永远不会居中,因为它似乎取决于 button.titleLabel 的大小。我已经尝试了许多关于按钮大小、图像大小、titleLabel 大小的计算,但从来没有完全居中。

有人遇到过同样的问题吗?

最佳答案

对于它的值(value),这里有一个通用的解决方案,可以将图像定位在文本上方的中心,而不使用任何魔数(Magic Number)。 请注意,以下代码已过时,您可能应该使用以下更新版本之一:

// the space between the image and text
CGFloat spacing = 6.0;

// lower the text and push it left so it appears centered 
//  below the image
CGSize 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 text
CGSize 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 text
CGFloat spacing = 6.0;

// lower the text and push it left so it appears centered 
//  below the image
CGSize 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 text
CGSize 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 clipping
CGFloat 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
    )
  }
}

关于ios - UIButton:如何使用 imageEdgeInsets 和 titleEdgeInsets 使图像和文本居中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2451223/

相关文章:

ios - 如果我必须下载 image.png 和 image@2x.png 从服务器上传到哪里?

iOS 应用程序需要 arm64 吗?

ios - 检测设备是否为 iPhone X

ios - 如何以编程方式更改添加到 iOS 上的 NIB 的 UIButton 的背景图像?

iphone - 根据存储在 NSArray 中特定索引处的图像以编程方式设置 UIButton 的图像

ios - 如何链接两个相互连接的 Collection View ?

ios - 在后台线程上保存到 CoreData Context

objective-c - 如何添加两个 NSNumber 对象?

objective-c - 在 iPad 上使用 UIActionSheet

iphone - 通过代码关闭警报 View