为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

饮歌长啸 2019-12-07 14:13:17
如果我只在按钮中放置一个图像,然后将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大小进行许多计算,并且永远都无法完美地居中。有人已经遇到了同样的问题吗?
查看完整描述

3 回答

?
呼如林

TA贡献1798条经验 获得超3个赞

对于它的价值,这是一种将图像居中放置在文本上方而不使用任何幻数的通用解决方案。请注意,以下代码已过时,您可能应该使用以下更新版本之一:


// 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

    )

  }

}


查看完整回答
反对 回复 2019-12-07
?
慕莱坞森

TA贡献1810条经验 获得超4个赞

找到了。


首先,配置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)];

现在,图像和文本将居中(在此示例中,图像显示在文本上方)。


查看完整回答
反对 回复 2019-12-07
?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

您可以使用此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控件子类化。即,从理论上讲,它们可能会在将来的版本中中断。


查看完整回答
反对 回复 2019-12-07
  • 3 回答
  • 0 关注
  • 484 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信