Autolayout - UIButton的内在大小不包括标题插入

时间:2013-07-23 01:52:53

标签: ios cocoa-touch uiview uibutton autolayout

如果我使用autolayout安排了UIButton,它的大小可以很好地调整以适应其内容。

如果我将图像设置为button.image,则内在尺寸似乎再次考虑到这一点。

但是,如果我调整按钮的titleEdgeInsets,布局不会考虑到这一点,而是截断按钮标题。

如何确保按钮的固有宽度占插图?

enter image description here

编辑:

我使用以下内容:

[self.backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 5, 0, 0)];

目标是在图像和文本之间添加一些分隔。

12 个答案:

答案 0 :(得分:185)

通过使用负面和正面标题和内容插入的组合,您可以在Interface Builder中使用它(无需编写任何代码)。

enter image description here

更新 :Xcode 7有一个错误,您无法在Right插入字段中输入负值,但您可以使用步进控制在它旁边减少价值。 (感谢Stuart)

这样做会在图像和标题之间添加8pt的间距,并且会增加按钮的固有宽度相同的量。像这样:

enter image description here

答案 1 :(得分:165)

您可以在不必覆盖任何方法或设置任意宽度约束的情况下解决此问题。您可以在Interface Builder中完成所有操作,如下所示。

  • 内在按钮宽度源自标题宽度加上图标宽度加上左右内容边缘插入。

  • 如果按钮同时包含图像和文本,则它们将作为一个组居中,两者之间没有填充。

  • 如果添加左侧内容插入,则相对于文本计算,而不是文本+图标。

  • 如果您设置了负左图像插图,则图像会向左拉出,但整体按钮宽度不受影响。

  • 如果设置负左图像插图,则实际布局使用该值的一半。因此,为了获得-20点左边的插入,你必须在Interface Builder中使用-40点左边的插入值。

因此,您提供了足够大的左侧内容插图,以便为所需的左侧插入创建图标和文本之间的内部填充空间,然后通过将图标和文本的数量加倍来向左移动图标在图标和文本之间填充。结果是一个左右内容相同的按钮,以及作为一个组居中的文本和图标对,它们之间有特定的填充量。

一些示例值:

// Produces a button with the layout:
// |-20-icon-10-text-20-|
// AutoLayout intrinsic width works as you'd desire.
button.contentEdgeInsets = UIEdgeInsetsMake(10, 30, 10, 20)
button.imageEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0)

答案 2 :(得分:92)

为什么不在UIView上覆盖intrinsicContentSize方法?例如:

- (CGSize) intrinsicContentSize
{
    CGSize s = [super intrinsicContentSize];

    return CGSizeMake(s.width + self.titleEdgeInsets.left + self.titleEdgeInsets.right,
                      s.height + self.titleEdgeInsets.top + self.titleEdgeInsets.bottom);
}

这应该告诉autolayout系统它应该增加按钮的大小以允许插入并显示全文。我不是在自己的电脑上,所以我没有测试过。

答案 3 :(得分:83)

你还没有指定你如何设置插图,所以我猜你正在使用titleEdgeInsets,因为我看到你得到的效果相同。如果我使用contentEdgeInsets,它可以正常工作。

- (IBAction)ChangeTitle:(UIButton *)sender {
    self.button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20);
    [self.button setTitle:@"Long Long Title" forState:UIControlStateNormal];
}

答案 4 :(得分:19)

对于斯威夫特来说,这是:

extension UIButton {
    override open var intrinsicContentSize: CGSize {
        let intrinsicContentSize = super.intrinsicContentSize

        let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
        let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom

        return CGSize(width: adjustedWidth, height: adjustedHeight)
    }
}

Love U Swift

答案 5 :(得分:18)

这个帖子有点老了,但我自己遇到了这个问题并且能够通过使用负插入来解决它。例如,在此处替换所需的填充值:

UIButton* myButton = [[UIButton alloc] init];
// setup some autolayout constraints here
myButton.titleEdgeInsets = UIEdgeInsetsMake(-desiredBottomPadding,
                                            -desiredRightPadding,
                                            -desiredTopPadding,
                                            -desiredLeftPadding);

结合正确的自动布局限制,您最终会得到一个包含图像和文字的自动调整大小按钮!如下所示,desiredLeftPadding设置为10。

Button with image and short text

Button with image and long text

你可以看到按钮的实际框架没有包含标签(因为标签在边界外向右移动了10个点),但是我们在文本和文本之间实现了10个填充点。图片。

答案 6 :(得分:8)

对于 Swift 3 ,基于pegpeg的回答:

extension UIButton {

    override open var intrinsicContentSize: CGSize {

        let intrinsicContentSize = super.intrinsicContentSize

        let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
        let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom

        return CGSize(width: adjustedWidth, height: adjustedHeight)

    }

}

答案 7 :(得分:6)

以上所有内容均不适用于 iOS 9 + ,我所做的是:

  • 添加宽度约束(当按钮没有任何文本时,为最小宽度。如果提供文本,按钮将自动缩放)
  • 将关系设置为大于或等于

enter image description here

现在要在按钮周围添加边框,只需使用以下方法:

10

答案 8 :(得分:4)

我想在我的UIButton图标和标签之间添加一个5pt的空间。这就是我实现它的方式:

UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeCustom];
// more button config etc
infoButton.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 5);
infoButton.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 0, -5);

contentEdgeInsets,titleEdgeInsets和imageEdgeInsets相互关联的方式需要从每个插图中获取一些东西。因此,如果您在标题左侧添加一些插入内容,则必须在右侧添加负插入内容,并在内容右侧提供更多空间(通过正插入)。

通过添加正确的内容插件来匹配标题插入内容的移位,我的文字不会超出按钮的范围。

答案 9 :(得分:3)

该选项也可在界面构建器中使用。见插图。我向左和向右设置为3.工作就像一个魅力。

Interface builder screenshot

答案 10 :(得分:1)

我使用的解决方案是在按钮上添加宽度约束。然后在初始化的某个地方,在设置文本后,更新宽度约束,如下所示:

self.buttonWidthConstraint.constant = self.shareButton.intrinsicContentSize.width + 8;

其中8是你的插图。

答案 11 :(得分:0)

调用sizeToFit()确保contentEdgeInset生效

 extension UIButton {

              open override func draw(_ rect: CGRect) { 
                    self.contentEdgeInsets = UIEdgeInsets(top: 10,left: 40,bottom: 10,right: 40)
                    self.sizeToFit()
              }
           }