我想在两行文本的左边放置一个图标,这样在图像和文本开始之间有大约2-3像素的空间。控件本身水平居中对齐(通过接口生成器设置)

这个按钮应该是这样的:

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

我试图配置这与contenttedgeinset, 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居中图像和文本?


当前回答

在Xcode 8.0中,你可以通过改变大小检查器中的insets来实现。

选择UIButton ->属性检查器->进入大小检查器,修改内容,图像和标题插入。

如果你想改变右边的图像,你可以简单地在属性检查器中将语义属性更改为强制从右向左。

其他回答

我将根据更新的Xcode 13更新答案。

用于图像和文本对齐。我们不需要使用任何扩展或一行代码。Xcode在属性选项卡中提供了预定义属性,如下图所示。

位置属性有4个图像属性——顶部、底部、前导和尾部

下面是一个如何使用imageEdgeInsets的简单示例 这将创建一个30x30的按钮,可点击区域增大10个像素(50x50)

    var expandHittableAreaAmt : CGFloat = 10
    var buttonWidth : CGFloat = 30
    var button = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
    button.frame = CGRectMake(0, 0, buttonWidth+expandHittableAreaAmt, buttonWidth+expandHittableAreaAmt)
    button.imageEdgeInsets = UIEdgeInsetsMake(expandHittableAreaAmt, expandHittableAreaAmt, expandHittableAreaAmt, expandHittableAreaAmt)
    button.setImage(UIImage(named: "buttonImage"), forState: .Normal)
    button.addTarget(self, action: "didTouchButton:", forControlEvents:.TouchUpInside)

我同意imageEdgeInsets和titleEdgeInsets的文档应该更好,但我想出了如何获得正确的定位而不求助于试验和错误。

这个问题的大意是,如果你想同时以文本和图像为中心。我们不希望图像和文本分别居中,我们希望图像和文本作为一个单独的实体放在一起。这实际上是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 + h位置。

@interface UIButton(ImageTitleCentering)

-(void) centerButtonAndImageWithSpacing:(CGFloat)spacing;

@end

公元UIButton +位置。

@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];

当然,你可能会想要为此创建一个很好的方法,可能会添加第二个类别方法,这是留给读者的练习。

快4.倍

extension UIButton {
    func centerTextAndImage(spacing: CGFloat) {
        let insetAmount = spacing / 2
        let writingDirection = UIApplication.shared.userInterfaceLayoutDirection
        let factor: CGFloat = writingDirection == .leftToRight ? 1 : -1

        self.imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount*factor, bottom: 0, right: insetAmount*factor)
        self.titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount*factor, bottom: 0, right: -insetAmount*factor)
        self.contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
    }
}

用法:

button.centerTextAndImage(spacing: 10.0)

如果您不想使用按钮配置的原因不同的情况。你可以实现下面的函数。

如果您将图像设置为按钮。你可以随意使用按钮imageView。更改按钮的位置imageView。函数,实现您输入的值作为偏移从您的按钮的前导锚。

private func leftPadding(value: CGFloat, button: UIButton) {
    button.imageView?.translatesAutoresizingMaskIntoConstraints = false
    button.imageView?.leadingAnchor.constraint(equalTo: button.leadingAnchor, constant: value).isActive = true
    button.imageView?.centerYAnchor.constraint(equalTo: button.centerYAnchor).isActive = true
}