Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autolayout - intrinsic size of UIButton does not include title insets

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.

like image 806
Ben Packard Avatar asked Oct 01 '22 08:10

Ben Packard


2 Answers

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.

enter image description here

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

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:

enter image description here

like image 233
n.Drake Avatar answered Oct 19 '22 12:10

n.Drake


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)
like image 205
jaredsinclair Avatar answered Oct 19 '22 12:10

jaredsinclair