将UIButton上的文本和图像与imageEdgeInsets和titleEdgeInsets对齐

我想在文本的两行左边放置一个图标,使图像和文本的起始位置之间有大约2-3像素的空间。 控件本身是水平对齐的(通过Interface Builder设置)

这个按钮就像这样:

|                  |
|[Image] Add To    |
|        Favorites |

我试图用contentEdgeInset,imageEdgeInsets和titleEdgeInsets来配置这个功能无济于事。 我知道负值会扩大边缘,而正值会缩小边缘,使其更靠近中心。

我试过了:

[button setTitleEdgeInsets:UIEdgeInsetsMake(0, -image.size.width, 0, 0)];
[button setImageEdgeInsets:UIEdgeInsetsMake(0, button.titleLabel.bounds.size.width, 0, 0)];

但是这并不能正确显示。 我一直在调整这些值,但是从左边插入值的-5到-10的值并没有以预期的方式移动。 -10会将文字一路向左滑动,所以我预期-5会从左侧滑向一半,但它不会。

插页背后的逻辑是什么? 我不熟悉图片展示位置和相关术语。

我用这个SO问题作为参考,但有关我的价值观是不正确的。 UIButton:如何使用imageEdgeInsets和titleEdgeInsets将图像和文本居中?


我同意imageEdgeInsetstitleEdgeInsets上的文档应该更好,但我想出了如何在不借助试验和错误的情况下获得正确的定位。

这个问题的总体思路就在这里,但那是如果你想要文本和图像都居中。 我们不希望图像和文本单独居中,我们希望将图像和文本作为一个整体集中在一起。 这实际上是UIButton已经做到的,所以我们只需要调整间距。

CGFloat spacing = 10; // the amount of spacing to appear between image and title
tabBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, spacing);
tabBtn.titleEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, 0);

我也把它变成了UIButton的一个类别,所以它很容易使用:

的UIButton + Position.h

@interface UIButton(ImageTitleCentering)

-(void) centerButtonAndImageWithSpacing:(CGFloat)spacing;

@end

的UIButton + Position.m

@implementation UIButton(ImageTitleCentering)

-(void) centerButtonAndImageWithSpacing:(CGFloat)spacing {
    self.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, spacing);
    self.titleEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, 0);
}

@end

所以我现在要做的就是:

[button centerButtonAndImageWithSpacing:10];

我每次都得到我需要的东西。 不需要手动更改边缘插槽。

编辑:交换图像和文本

回应@Javal的评论

使用这种相同的机制,我们可以交换图像和文本。 要完成交换,只需使用负间距,但还要包括文本和图像的宽度。 这将要求帧已知并且布局已经执行。

[self.view layoutIfNeeded];
CGFloat flippedSpacing = -(desiredSpacing + button.currentImage.size.width + button.titleLabel.frame.size.width);
[button centerButtonAndImageWithSpacing:flippedSpacing];

当然,你可能想为此做一个好的方法,可能会增加第二类方法,这是读者的一个练习。


我对这次派对有点迟,但我认为我有一些有用的补充。

Kekoa的回答非常好,但正如RonLugge所说,它可以使按钮不再尊重sizeToFit或者更重要的是,可以在按钮固有大小时使按钮剪辑它的内容。 哎呀!

首先,虽然,

我相信imageEdgeInsetstitleEdgeInsets工作原理的简短说明:

imageEdgeInsets的文档部分说明如下:

使用此属性来调整和重新定位按钮图像的有效绘制矩形。 您可以为四个插图(顶部,左侧,底部,右侧)中的每一个指定不同的值。 正值缩小或缩小,使边缘靠近按钮的中心。 负值会扩大或突破该边缘。

我相信这个文档写的是想象按钮没有标题,只是一个图像。 通过这种方式,我们有了更多的想法,并且表现出UIEdgeInsets通常的做法。 基本上,图像的框架(或标题, titleEdgeInsets )向内移动以获得正向插入,向外移动以获得负插入。

好的,那是什么?

我快到那里了! 以下是默认设置,设置图像和标题(按钮边框为绿色以显示其位置):

如果您想要在图像和标题之间进行间隔,而不会导致图像和标题之间的间隔,则需要设置四个不同的插页,每个图像和标题都有两个插页。 这是因为你不想改变这些元素的框架大小,而只是改变它们的位置。 当你开始以这种方式思考时,对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

但是,等一下,你说,当我这样做时,我得到这个:

哦耶! 我忘了,文件警告我这件事。 他们说,部分:

此属性仅用于在布局过程中定位图像。 该按钮不使用此属性来确定intrinsicContentSizesizeThatFits:

但有一个属性可以帮助,那就是contentEdgeInsets 。 该文档部分说:

该按钮使用此属性来确定intrinsicContentSizesizeThatFits:

听起来不错。 所以让我们再来调整一下类别:

@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

你会得到什么?

看起来像我的赢家。


在斯威夫特工作,不想做任何思考? 以下是Swift扩展的最终版本:

extension UIButton {
    func centerTextAndImage(spacing: CGFloat) {
        let insetAmount = spacing / 2
        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)
    }
}

在界面生成器中。 选择UIButton - > Attributes Inspector - > Edge = Title并修改边缘插页

链接地址: http://www.djcxy.com/p/4837.html

上一篇: Aligning text and image on UIButton with imageEdgeInsets and titleEdgeInsets

下一篇: UILabel text margin