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

Ben*_*ard 184 cocoa-touch uibutton uiview ios autolayout

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

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

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

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

在此输入图像描述

编辑:

我使用以下内容:

[self.backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
Run Code Online (Sandbox Code Playgroud)

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

n.D*_*ake 198

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

在此输入图像描述

更新:Xcode 7有一个错误,您无法在RightInset字段中输入负值,但您可以使用旁边的步进控件来减小值.(谢谢斯图尔特)

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

在此输入图像描述

  • 我不明白它是如何工作的...但它确实-_- (12认同)
  • 这个技巧不再适用.接口构建器不再接受"Right"字段中的负值. (7认同)
  • @JorisMans你不能_type_负值,但它通过使用文本字段右侧的步进控件降低到所需的负值对我有用...去图! (7认同)
  • 这应该是第一个答案,为什么会在这里?在找到这个之前我已经尝试了其他5个...... (3认同)
  • 它使用contentEdgeInsets(这不是错误)让autolayout增加按钮宽度.并将标签移动到右侧的空白区域.巧妙地解决标题边缘插入错误的方法. (2认同)
  • 我做了内容插入16的权利,使文本在UIButton中居中 (2认同)

jar*_*air 178

您可以解决此问题,而无需覆盖任何方法或设置任意宽度约束.您可以在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)
Run Code Online (Sandbox Code Playgroud)


Maa*_*ten 93

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

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

    return CGSizeMake(s.width + self.titleEdgeInsets.left + self.titleEdgeInsets.right,
                      s.height + self.titleEdgeInsets.top + self.titleEdgeInsets.bottom);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 对我来说,UIButton的`intrinsicContentSize`应该添加到titleEdgeInsets中,我将向Apple提交一个bug. (35认同)
  • 我同意,对于imageEdgeInsets也一样. (6认同)
  • `intrinsicContentSize`是UIView上的一个方法,而不是UIButton,所以你不会搞乱任何UIButton方法.Apple并不认为这是一个问题:"重写此方法允许自定义视图与布局系统进行通信,根据其内容,它的大小." OP没有透露任何关于不同按钮的信息,只有一个. (2认同)

rde*_*mar 85

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

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

  • 这不能回答使用图像时需要调整图像和标题之间插图的问题! (27认同)
  • 这是更好的解决方案,因为它完全符合您的要求,而无需触及intrinsicContentSize. (3认同)

peg*_*peg 23

而对于Swift的工作:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

爱你斯威夫特

  • 即使你不应该这样做,在这种情况下最好进行子类化,因为苹果文档明确指出内在大小在其计算中不包括 titleEdgeInsets,因此通过使用扩展,你不仅违反了苹果的期望,而且违反了所有其他阅读过的开发人员的期望文档。 (3认同)

Bri*_*tle 18

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

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

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

带图像和短文本的按钮

带图像和长文本的按钮

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


The*_*eoK 9

对于基于pegpeg答案的Swift 3:

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)

    }

}
Run Code Online (Sandbox Code Playgroud)


Ori*_*itm 6

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

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

在此输入图像描述

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

button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20);
Run Code Online (Sandbox Code Playgroud)


orj*_*orj 5

我想在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);
Run Code Online (Sandbox Code Playgroud)

contentEdgeInsets,titleEdgeInsets和imageEdgeInsets相互关联的方式要求每个插图都有一些让步。因此,如果您在标题的左侧添加一些插图,则必须在右侧添加负插图,并在内容右侧提供更多空间(通过正插图)。

通过添加正确的内容插图以匹配标题插图的偏移,我的文本不会超出按钮的范围。