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


159

如果仅在按钮中放置图像,然后将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大小进行许多计算,并且永远都无法完美地居中。

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

Answers:


412

对于它的价值,这是一个通用的解决方案,无需使用任何幻数即可将图像定位在文本上方的中心位置。请注意,以下代码已过时,您可能应该使用以下更新版本之一

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

5
太好了-谢谢!我认为还有很多其他答案可以解决这种“困难的方法”-这看起来要好得多。
Joe D'Andrea

3
我发现以上内容可以使人满意,但我绝对不知道如何做。任何人都可以获得有关各个EdgeInsets参数会影响哪些内容的图形说明的链接?为什么文字宽度会改变?
罗伯特·阿特金斯

3
当缩小图像以适合按钮时,此功能不起作用。似乎UIButton(至少在iOS 7中)使用image.size而不是imageView.frame.size进行居中计算。
丹·杰克逊

5
@Hemang和Dan Jackson,我合并了您的建议,而未自己测试它们。我最初为iOS 4编写此代码时觉得很荒谬,在经过如此众多的版本之后,我们仍然必须对Apple的布局算法进行实质上的反向工程才能获得如此明显的功能。或者至少我认为,一致的支持和下面同样骇人听闻的答案(没有侮辱的意图)尚无更好的解决方案。
杰西·克罗斯森

5
在iOS8中,我发现最好使用button.currentTitle代替,button.titleLabel.text尤其是如果按钮文本将永远更改的话。currentTitle会立即填充,而titleLabel.text更改速度可能会很慢,这会导致未对齐的插图。
mjangda

59

找到了。

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

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

干杯。


3
七岁 真的不记得了。当我问时,我回答了自己(我的回答是当时唯一的回答)。当当前选定答案的作者专注于消除那些不可思议的数字时,我已经更改了选定答案。因此,在选定的答案中,您可以弄清楚它们的含义。
reinaldoluckman'4

20

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


在iOS9上测试。图片居中,但文字显示在左侧:(
endavid

13

编辑:更新为Swift 3

如果您正在寻找Jesse Crossen答案的Swift解决方案,可以将其添加到UIButton的子类中:

override func layoutSubviews() {

    let spacing: CGFloat = 6.0

    // lower the text and push it left so it appears centered
    //  below the image
    var titleEdgeInsets = UIEdgeInsets.zero
    if let image = self.imageView?.image {
        titleEdgeInsets.left = -image.size.width
        titleEdgeInsets.bottom = -(image.size.height + spacing)
    }
    self.titleEdgeInsets = titleEdgeInsets

    // raise the image and push it right so it appears centered
    //  above the text
    var imageEdgeInsets = UIEdgeInsets.zero
    if let text = self.titleLabel?.text, let font = self.titleLabel?.font {
        let attributes = [NSFontAttributeName: font]
        let titleSize = text.size(attributes: attributes)
        imageEdgeInsets.top = -(titleSize.height + spacing)
        imageEdgeInsets.right = -titleSize.width
    }
    self.imageEdgeInsets = imageEdgeInsets

    super.layoutSubviews()
}

9

这里有一些很好的例子,但是当我还要处理多行文本(文本换行)时,我无法在所有情况下都使用它。为了使它最终起作用,我结合了两种技术:

  1. 我在上面使用了Jesse Crossen示例。但是,我解决了文本高度问题,并添加了指定水平文本边距的功能。在允许自动换行时,边距非常有用,这样它就不会碰到按钮的边缘:

    // the space between the image and text
    CGFloat spacing = 10.0;
    float   textMargin = 6;
    
    // get the size of the elements here for readability
    CGSize  imageSize   = picImage.size;
    CGSize  titleSize   = button.titleLabel.frame.size;
    CGFloat totalHeight = (imageSize.height + titleSize.height + spacing);      // get the height they will take up as a unit
    
    // lower the text and push it left to center it
    button.titleEdgeInsets = UIEdgeInsetsMake( 0.0, -imageSize.width +textMargin, - (totalHeight - titleSize.height), +textMargin );   // top, left, bottom, right
    
    // the text width might have changed (in case it was shortened before due to 
    // lack of space and isn't anymore now), so we get the frame size again
    titleSize = button.titleLabel.bounds.size;
    
    button.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + spacing), 0.0, 0.0, -titleSize.width );     // top, left, bottom, right        
  2. 确保设置文本标签以换行

    button.titleLabel.numberOfLines = 2; 
    button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
    button.titleLabel.textAlignment = UITextAlignmentCenter;
  3. 现在大多数情况下都可以使用。但是,我有一些按钮无法正确呈现其图像。图像要么向右或向左移动(未居中)。因此,我使用了UIButton布局覆盖技术来强制imageView居中。

    @interface CategoryButton : UIButton
    @end
    
    @implementation CategoryButton
    
    - (void)layoutSubviews
    {
        // Allow default layout, then center imageView
        [super layoutSubviews];
    
        UIImageView *imageView = [self imageView];
        CGRect imageFrame = imageView.frame;
        imageFrame.origin.x = (int)((self.frame.size.width - imageFrame.size.width)/ 2);
        imageView.frame = imageFrame;
    }
    @end

似乎这是一个很好的解决方案,但是button.titleLabel.numberOfLines不应为0,这样它可以根据需要设置多行吗?
Ben Lachman

就我而言,我最多只需要两行。否则,图像会出现按钮整体尺寸问题。
Tod Cunningham

9

我为@TodCunningham的答案做了一个方法

 -(void) AlignTextAndImageOfButton:(UIButton *)button
 {
   CGFloat spacing = 2; // the amount of spacing to appear between image and title
   button.imageView.backgroundColor=[UIColor clearColor];
   button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
   button.titleLabel.textAlignment = UITextAlignmentCenter;
   // get the size of the elements here for readability
   CGSize imageSize = button.imageView.frame.size;
   CGSize titleSize = button.titleLabel.frame.size;

  // lower the text and push it left to center it
  button.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, - (imageSize.height   + spacing), 0.0);

  // the text width might have changed (in case it was shortened before due to 
  // lack of space and isn't anymore now), so we get the frame size again
   titleSize = button.titleLabel.frame.size;

  // raise the image and push it right to center it
  button.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, -     titleSize.width);
 }

7

已针对Xcode 11+更新

我的原始答案中描述的插图已移至最新版本的Xcode中的大小检查器中。我尚不清楚100%何时发生切换,但是如果在属性检查器中未找到插入信息,则读者应检查大小检查器。以下是新插图屏幕的示例(从11.5版开始位于大小属性检查器的顶部)。

insets_moved_to_size_inspector

原始答案

其他答案没什么问题,但是我只想指出,使用零行代码可以在Xcode中直观地实现相同的行为。如果您不需要计算值或使用情节提要/ xib进行构建,则此解决方案很有用(否则适用其他解决方案)。

注意-我确实知道OP的问题是一个需要代码的问题。我只是出于完整性的目的提供此答案,并作为使用情节提要/ xib的人的合理选择。

要使用边缘插图修改按钮的图像,标题和内容视图上的间距,可以选择按钮/控件并打开属性检查器。向下滚动到检查器的中间,然后找到“边缘插图”部分。

边缘插入

人们还可以访问和修改标题,图像或内容视图的特定边缘插图。

菜单选项


我不明白的是为什么我似乎无法在情节提要中为某些值输入负数。
Daniel T.

它适用于较新的快速版本吗?我在任何地方都找不到Edge属性
brockhampton

@brockhampton-参见新答案的新位置
Tommie C.

6

不要打系统。如果您的布局变得过于复杂以至于无法使用Interface Builder +一些简单的配置代码进行管理,请使用更简单的方式手动进行布局layoutSubviews-这就是它的用途!其他一切都等于骇客。

创建一个UIButton子类,并重写其layoutSubviews方法以编程方式对齐文本和图像。或使用类似https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h之类的东西,以便可以使用块实现layoutSubviews。


6

子类UIButton

- (void)layoutSubviews {
    [super layoutSubviews];
    CGFloat spacing = 6.0;
    CGSize imageSize = self.imageView.image.size;
    CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake(self.frame.size.width, self.frame.size.height - (imageSize.height + spacing))];
    self.imageView.frame = CGRectMake((self.frame.size.width - imageSize.width)/2, (self.frame.size.height - (imageSize.height+spacing+titleSize.height))/2, imageSize.width, imageSize.height);
    self.titleLabel.frame = CGRectMake((self.frame.size.width - titleSize.width)/2, CGRectGetMaxY(self.imageView.frame)+spacing, titleSize.width, titleSize.height);
}

6

Jesse CrossenSwift 4的更新答案:

extension UIButton {
    func alignVertical(spacing: CGFloat = 6.0) {
        guard let imageSize = self.imageView?.image?.size,
            let text = self.titleLabel?.text,
            let font = self.titleLabel?.font
            else { return }
        self.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)
        let labelString = NSString(string: text)
        let titleSize = labelString.size(withAttributes: [kCTFontAttributeName as NSAttributedStringKey: font])
        self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0.0, bottom: 0.0, right: -titleSize.width)
        let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
        self.contentEdgeInsets = UIEdgeInsets(top: edgeOffset, left: 0.0, bottom: edgeOffset, right: 0.0)
    }
}

使用这种方式:

override func viewDidLayoutSubviews() {
    button.alignVertical()
}

经过许多小时。这是唯一有效的方法:)
哈里·布鲁

4

有了这段代码,您将获得如下内容 标题和图像对齐

extension UIButton {
    func alignTextUnderImage() {
        guard let imageView = imageView else {
                return
        }
        self.contentVerticalAlignment = .Top
        self.contentHorizontalAlignment = .Center
        let imageLeftOffset = (CGRectGetWidth(self.bounds) - CGRectGetWidth(imageView.bounds)) / 2//put image in center
        let titleTopOffset = CGRectGetHeight(imageView.bounds) + 5
        self.imageEdgeInsets = UIEdgeInsetsMake(0, imageLeftOffset, 0, 0)
        self.titleEdgeInsets = UIEdgeInsetsMake(titleTopOffset, -CGRectGetWidth(imageView.bounds), 0, 0)
    }
}

2
我写了一些小扩展名,用于在按钮内定位图像和文本。如果您有兴趣,这里是源代码。github.com/sssbohdan/ButtonAlignmentExtension/blob/master/...
博赫丹Savych

4

使用Swift 3+语法的UIButton扩展:

extension UIButton {
    func alignImageAndTitleVertically(padding: CGFloat = 6.0) {
        let imageSize: CGSize = imageView!.image!.size
        titleEdgeInsets = UIEdgeInsetsMake(0.0, -imageSize.width, -(imageSize.height + padding), 0.0)
        let labelString = NSString(string: titleLabel!.text!)
        let titleSize = labelString.size(attributes: [NSFontAttributeName: titleLabel!.font])
        self.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + padding), 0.0, 0.0, -titleSize.width)
        let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
        self.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0)
    }
}

原始答案:https//stackoverflow.com/a/7199529/3659227


3

杰西·克罗斯森(Jesse Crossen)的答案仅作了微小改动,就对我而言非常适用:

代替:

CGSize titleSize = button.titleLabel.frame.size;

我用了这个:

CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName:button.titleLabel.font}];

欢迎来到SO!您可以直接将其写给Jesse,而不是添加一个单独的答案(进行较小的更改),以便Jesse可以正确地检查和更新其[接受的]答案(如果需要)。
Hemang 2014年

3

使用button.titleLabel.frame.size.width作品精唯一,只要标签足够短,不会被截断。当标签文本被截断时,定位将不起作用。服用

CGSize titleSize = [[[button titleLabel] text] sizeWithFont:[[button titleLabel] font]];

即使标签文本被截断也可以为我工作。


你有波顿错别字。
比姆宾(Bhimbim)

2

我查看了现有的答案,但也发现设置按钮框架是重要的第一步。

这是我使用的一个函数来解决这个问题:

const CGFloat kImageTopOffset   = -15;
const CGFloat kTextBottomOffset = -25;

+ (void) centerButtonImageTopAndTextBottom: (UIButton*)         button 
                                     frame: (CGRect)            buttonFrame
                                      text: (NSString*)         textString
                                 textColor: (UIColor*)          textColor
                                      font: (UIFont*)           textFont
                                     image: (UIImage*)          image
                                  forState: (UIControlState)    buttonState
{
    button.frame = buttonFrame;

    [button setTitleColor: (UIColor*)       textColor
                 forState: (UIControlState) buttonState];

    [button setTitle: (NSString*) textString
            forState: (UIControlState) buttonState ];


    [button.titleLabel setFont: (UIFont*) textFont ];

    [button setTitleEdgeInsets: UIEdgeInsetsMake( 0.0, -image.size.width, kTextBottomOffset,  0.0)]; 

    [button setImage: (UIImage*)       image 
            forState: (UIControlState) buttonState ];

    [button setImageEdgeInsets: UIEdgeInsetsMake( kImageTopOffset, 0.0, 0.0,- button.titleLabel.bounds.size.width)];
}

2

或者,您可以只使用以下类别:

@interface UIButton (VerticalLayout)  

- (void)centerVerticallyWithPadding:(float)padding;  
- (void)centerVertically;  

@end  


@implementation UIButton (VerticalLayout)  

- (void)centerVerticallyWithPadding:(float)padding 
{      
    CGSize imageSize = self.imageView.frame.size;  
    CGSize titleSize = self.titleLabel.frame.size;  

    CGFloat totalHeight = (imageSize.height + titleSize.height + padding);  

    self.imageEdgeInsets = UIEdgeInsetsMake(- (totalHeight - imageSize.height),
                                            0.0f,
                                            0.0f,
                                            - titleSize.width);

    self.titleEdgeInsets = UIEdgeInsetsMake(0.0f,
                                            - imageSize.width,
                                            - (totalHeight - titleSize.height),
                                            0.0f);

}


- (void)centerVertically
{  
    const CGFloat kDefaultPadding = 6.0f;

    [self centerVerticallyWithPadding:kDefaultPadding];  
}  


@end

1
这不适用于自定义字体。从iOS7 +起CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName: button.titleLabel.font}];
Hemang 2014年

1

我的用例使插图难以处理:

  1. 按钮上的背景图像保持一致
  2. 动态文本和图像更改,其中字符串长度和图像大小有所不同

这就是我最终要做的事情,对此我感到非常满意:

  • 在故事板上创建带有背景图像的按钮(带有模糊和彩色的圆形圆圈)。

  • 在我的课程中声明一个UIImageView:

    @implementation BlahViewController {
        UIImageView *_imageView;
    }
  • 在init上创建图像视图实例:

    -(id)initWithCoder:(NSCoder *)aDecoder {
        self = [super initWithCoder:aDecoder];
        if (self) {
            _imageView = [[UIImageView alloc] initWithCoder:aDecoder];
         }
         return self;
     }
  • 在viewDidLoad中,将新层添加到图像视图的按钮中并设置文本对齐方式:

    [self.btn addSubview:_imageView];
    [self.btn.titleLabel setTextAlignment:NSTextAlignmentCenter];
  • 在按钮单击方法中,将我选择的覆盖图像添加到图像视图中,将其调整大小以适合图像并将其居中放置在按钮中,但将其向上移动15,以便可以将文本偏移量放在其下方:

    [_imageView setImage:[UIImage imageNamed:@"blahImageBlah]];
    [_imageView sizeToFit];
    _imageView.center = CGPointMake(ceilf(self.btn.bounds.size.width / 2.0f),
             ceilf((self.btn.bounds.size.height / 2.0f) - 15));
    [self.btn setTitle:@"Some new text" forState:UIControlStateNormal];

注意:ceilf()对于确保其位于像素边界上对于图像质量很重要。


1
对于我的用例来说,绝对也是一种更好的方法,因为我将按钮添加到了堆栈视图中。
valeCocoa

0

假设您希望文本和图像都水平居中,请将图像放在文本上方:从界面生成器居中放置文本并添加顶部插图(为图像腾出空间)。(将左插图保留为0)。使用界面生成器选择图像-它的实际位置将通过代码设置,因此不必担心IB中的情况看起来不会好。与上述其他答案不同,这实际上适用于当前所有受支持的ios版本(5、6和7)。

在代码中,只需在抓取图像后丢弃按钮的ImageView(通过将按钮的图像设置为null)(这也会自动使文本居中,并在必要时将其换行)。然后使用相同的帧大小和图像实例化您自己的ImageView并将其放置在中间。

这样,您仍然可以从界面生成器中选择图像(尽管它不会像模拟器中那样在IB中对齐,但是同样,其他解决方案在所有受支持的ios版本中都不兼容)


0

我很努力地做到这一点,因为我无法在视图的构造函数中获得图像大小和文本宽度。杰西答案的两个小变化对我有用:

CGFloat spacing = 3;
self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - image.size.width, - (image.size.height + spacing), 0.0);
CGSize titleSize = [name sizeWithAttributes:@{NSFontAttributeName:self.titleLabel.font}];
self.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

更改为:

  • 使用 [NSString sizeWithAttributes]获得的文本宽度;
  • 直接在UIImage而不是上获取图像尺寸UIImageView

0

这对我来说效果很好,对于具有不同图像宽度和标题长度的几个按钮:

子类 UIButton

override func layoutSubviews() {
    super.layoutSubviews()

    if let image = imageView?.image {

        let margin = 30 - image.size.width / 2
        let titleRect = titleRectForContentRect(bounds)
        let titleOffset = (bounds.width - titleRect.width - image.size.width - margin) / 2


        contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
            imageEdgeInsets = UIEdgeInsetsMake(0, margin, 0, 0)
            titleEdgeInsets = UIEdgeInsetsMake(0, (bounds.width - titleRect.width -  image.size.width - margin) / 2, 0, 0)
    }

}

0

对于尺寸为80x80像素的按钮,效果很好。

[self.leftButton setImageEdgeInsets:UIEdgeInsetsMake(0, 10.0, 20.0, 10.0)];    
[self.leftButton setTitleEdgeInsets:UIEdgeInsetsMake(60, -75.0, 0.0, 0.0)];

0

我做了一些调整,以使图像在水平中心对齐:

// the space between the image and text
        let spacing = CGFloat(36.0);

        // lower the text and push it left so it appears centered
        //  below the image
        let imageSize = tutorialButton.imageView!.frame.size;
        tutorialButton.titleEdgeInsets = UIEdgeInsetsMake(
            0, -CGFloat(imageSize.width), -CGFloat(imageSize.height + spacing), 0.0);

        // raise the image and push it right so it appears centered
        //  above the text
        let titleSize = tutorialButton.titleLabel!.frame.size;
        tutorialButton.imageEdgeInsets = UIEdgeInsetsMake(
            -CGFloat(titleSize.height + spacing), CGFloat((tutorialButton.frame.width - imageSize.width) / 2), 0.0, -CGFloat(titleSize.width));

0

使用边缘插图是强制性的吗?如果没有,您可以尝试相对于中心父视图定位

extension UIButton 
{
    func centerImageAndTextVerticaAlignment(spacing: CGFloat) 
    {
        var titlePoint : CGPoint = convertPoint(center, fromView:superview)
        var imageViewPoint : CGPoint = convertPoint(center, fromView:superview)
        titlePoint.y += ((titleLabel?.size.height)! + spacing)/2
        imageViewPoint.y -= ((imageView?.size.height)! + spacing)/2
        titleLabel?.center = titlePoint
        imageView?.center = imageViewPoint

    }
}

该问题明确要求使用imageEdgeInsets和titleEdgeInsets,因此可能是强制性的
Tibrogargan

0

您需要将图像向右移动文本的宽度。然后将文本向左移动图像的宽度。

UIEdgeInsets imageEdgeInsets = self.remoteCommandsButtonLights.imageEdgeInsets;
imageEdgeInsets.left = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:[button.titleLabel font]}].width;
imageEdgeInsets.bottom = 14.0;
button.imageEdgeInsets = imageEdgeInsets;

UIEdgeInsets titleEdgeInsets = self.remoteCommandsButtonLights.titleEdgeInsets;
titleEdgeInsets.left = -button.currentImage.size.width;
titleEdgeInsets.top = 20.0;
button.titleEdgeInsets = titleEdgeInsets;

然后调整顶部和底部插图以调整Y轴。也可以通过编程方式完成此操作,但对于您的图像大小应保持不变。而X轴插入将需要根据每个按钮中文本标签的大小进行更改。


0

在扩展Swift 4.2中添加此代码

 func moveImageLeftTextCenter(imagePadding: CGFloat = 30.0){
    guard let imageViewWidth = self.imageView?.frame.width else{return}
    guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
    self.contentHorizontalAlignment = .left
    imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imagePadding - imageViewWidth / 2, bottom: 0.0, right: 0.0)
    titleEdgeInsets = UIEdgeInsets(top: 0.0, left: (bounds.width - titleLabelWidth) / 2 - imageViewWidth, bottom: 0.0, right: 0.0)
}
func moveImageRIghtTextCenter(imagePadding: CGFloat = 30.0){
    guard let imageViewWidth = self.imageView?.frame.width else{return}
    guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
    self.contentHorizontalAlignment = .right
    imageEdgeInsets = UIEdgeInsets(top: 0.0, left:0.0 , bottom: 0.0, right: imagePadding - imageViewWidth / 2)
    titleEdgeInsets = UIEdgeInsets(top: 0.0, left:0.0 , bottom: 0.0, right:(bounds.width - titleLabelWidth) / 2 - imageViewWidth)
}

0

只需投入2美分,这对我有用:

extension UIButton {
  public func centerImageAndTextVertically(spacing: CGFloat) {
    layoutIfNeeded()
    let contentFrame = contentRect(forBounds: bounds)
    let imageFrame = imageRect(forContentRect: contentFrame)
    let imageLeftInset = bounds.size.width * 0.5 - imageFrame.size.width * 0.5
    let imageTopInset = -(imageFrame.size.height + spacing * 0.5)
    let titleFrame = titleRect(forContentRect: contentFrame)
    let titleLeftInset = ((bounds.size.width - titleFrame.size.width) * 0.5) - imageFrame.size.width
    let titleTopInmset = titleFrame.size.height + spacing * 0.5
    imageEdgeInsets = UIEdgeInsets(top: imageTopInset, left: imageLeftInset, bottom: 0, right: 0)
    titleEdgeInsets = UIEdgeInsets(top: titleTopInmset, left: titleLeftInset, bottom: 0, right: 0)
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.