ios 自动布局 - UIButton 的内在大小不包括标题插入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17800288/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:27:57  来源:igfitidea点击:

Autolayout - intrinsic size of UIButton does not include title insets

ioscocoa-touchuiviewuibuttonautolayout

提问by Ben Packard

If I have a UIButton arranged using autolayout, its size adjusts nicely to fit its content.

如果我有一个使用自动布局排列的 UIButton,它的大小会很好地调整以适应其内容。

If I set an image as button.image, the instrinsic size again seems to account for this.

如果我将图像设置为button.image,则内在大小似乎再次说明了这一点。

However, if I tweak the titleEdgeInsetsof the button, the layout does not account for this and instead truncates the button title.

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

How can I ensure that the intrinsic width of the button accounts for the inset?

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

enter image description here

在此处输入图片说明

Edit:

编辑:

I am using the following:

我正在使用以下内容:

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

The goal is to add some separation between the image and the text.

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

采纳答案by jaredsinclair

You can solve this without having to override any methods or set an arbitrary width constraint. You can do it all in Interface Builder as follows.

您无需覆盖任何方法或设置任意宽度约束即可解决此问题。您可以按如下方式在 Interface Builder 中完成所有操作。

  • Intrinsic button width is derived from the title width plus the icon width plus the left and right contentedge insets.

  • If a button has both an image and text, they're centered as a group, with no padding between.

  • If you add a left content inset, it's calculated relative to the text, not the text + icon.

  • If you set a negative left image inset, the image is pulled out to the left but the overall button width is unaffected.

  • If you set a negative left image inset, the actual layout uses half that value. So to get a -20 point left inset, you must use a -40 point left inset value in Interface Builder.

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

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

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

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

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

So you provide a big enough left content inset to create space for both the desired left inset andthe inner padding between the icon and the text, and then shift the icon left by doubling the amount of padding you want between the icon and the text. The result is a button with equal left and right content insets, and a text and icon pair that are centered as a group, with a specific amount of padding between them.

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

Some example values:

一些示例值:

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

回答by n.Drake

You can get this to work in Interface Builder (without writing any code), by using a combination of negative and positive Title and Content Insets.

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

enter image description here

在此处输入图片说明

Update: Xcode 7 has a bug where you cannot enter negative values in the RightInset field, but you can use the stepper control next to it to decrease the value. (Thanks Stuart)

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

Doing this will add 8pt of spacing between the image and the title and will increase the intrinsic width of the button by the same amount. Like this:

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

enter image description here

在此处输入图片说明

回答by Maarten

Why not override the intrinsicContentSizemethod on UIView? For example:

为什么不覆盖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);
}

This should tell the autolayout system that it should increase the size of the button to allow for the insets and show the full text. I'm not at my own computer, so I haven't tested this.

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

回答by rdelmar

You haven't specified how you're setting the insets, so I'm guessing that you're using titleEdgeInsets because I see the same effect you're getting. If I use contentEdgeInsets instead it works properly.

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

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

回答by pegpeg

And for Swift worked this:

而对于斯威夫特来说:

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

爱你斯威夫特

回答by Brian Gerstle

This thread is a bit old, but I just ran into this myself and was able to solve it by using a negative inset. For example, substitute your desired padding values here:

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

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

Combined with the right autolayout constraints, you end up with an auto-resizing button which contains an image and text! Seen below with desiredLeftPaddingset to 10.

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

Button with image and short text

带有图像和短文本的按钮

Button with image and long text

带有图像和长文本的按钮

You can see that the actual frame of the button doesn't encompass the label (since the label is shifted 10 points to the right, outside the bounds), but we've achieved 10 points of padding between the text and the picture.

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

回答by TheoK

For Swift 3based on pegpeg's answer:

对于基于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)

    }

}

回答by Oritm

All above did not work for iOS 9+, what i did is:

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

  • Add a width constraint (for a minimum width when the button doesn't have any text. The button will auto scale if text is provided)
  • set the relation to Greater Than or Equal
  • 添加宽度约束(当按钮没有任何文本时的最小宽度。如果提供文本,按钮将自动缩放)
  • 将关系设置为大于或等于

enter image description here

在此处输入图片说明

Now to add a border around the button just use the method:

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

button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20);

回答by orj

I wanted to add a 5pt space between my UIButton icon and the label. This is how I achieved it:

我想在我的 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);

The way contentEdgeInsets, titleEdgeInsets and imageEdgeInsets relate to each other requires a little give and take from each inset. So if you add some insets to the title's left you have to add negative inset on the right and provide some more space (via a positive inset) on the content right.

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

By adding a right content inset to match the shift of the title insets my text doesn't go outside the bounds of the button.

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

回答by zeiteisen

The option is also available in interface builder. See the Inset. I set left and right to 3. Works like a charm.

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

Interface builder screenshot

界面生成器截图