Autolayout - intrinsic size of UIButton does not i

2019-01-20 22:04发布

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

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

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

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.

12条回答
啃猪蹄的小仙女
2楼-- · 2019-01-20 22:32

calling sizeToFit() makes sure that contentEdgeInset is taken into effect

 extension UIButton {

              open override func draw(_ rect: CGRect) { 
                    self.contentEdgeInsets = UIEdgeInsets(top: 10,left: 40,bottom: 10,right: 40)
                    self.sizeToFit()
              }
           }
查看更多
Ridiculous、
3楼-- · 2019-01-20 22:37

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

Interface builder screenshot

查看更多
相关推荐>>
4楼-- · 2019-01-20 22:38

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.

  • Intrinsic button width is derived from the title width plus the icon width plus the left and right content edge 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.

So you provide a big enough left content inset to create space for both the desired left inset and the 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)
查看更多
神经病院院长
5楼-- · 2019-01-20 22:38

Why not override the intrinsicContentSize method on UIView? For example:

- (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.

查看更多
Evening l夕情丶
6楼-- · 2019-01-20 22:39

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

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.

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.

查看更多
啃猪蹄的小仙女
7楼-- · 2019-01-20 22:40

For Swift 3 based on pegpeg's answer:

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)

    }

}
查看更多
登录 后发表回答