72

I have the following layout, and I'm trying to add a padding to the left and right..

The controls are a disabled UIButton.

enter image description here

My code for creating a button is this:

UIButton *buttonTime = [[UIButton alloc] initWithFrame:CGRectMake(90, 10, 50, 20)]; 
[buttonTime setBackgroundImage:[[UIImage imageNamed:@"bubble.png"] stretchableImageWithLeftCapWidth:9 topCapHeight:13] forState:UIControlStateDisabled];

[buttonTime setTitle:@"27 feb, 2011 11:10 PM" forState:UIControlStateDisabled];             
[buttonTime setTitleColor:[UIColor blackColor] forState:UIControlStateDisabled];
buttonTime.titleLabel.font=[UIFont fontWithName:@"Helvetica" size:8.0]; 
buttonTime.titleLabel.lineBreakMode= UILineBreakModeWordWrap;
[buttonTime setEnabled:FALSE];
[scrollView addSubview:buttonTime];
[buttonTime release];
pkamb
  • 26,648
  • 20
  • 124
  • 157
PartySoft
  • 2,539
  • 7
  • 36
  • 55
  • d= (-_- ) `iOS` has nothing comparable to `Android`'s padding, I mean, all `insets` (no matter if it's title or `contentEdgeInsets`) just keep changing content's visual-position (never actual width or height, unlike Android's padding). So, happy working around! – Top-Master Apr 03 '21 at 20:30

10 Answers10

95

You can also set the inset values from the Interface Builder Size Inspector inside a Storyboard or xib.

Interface Builder Size Inspector

pkamb
  • 26,648
  • 20
  • 124
  • 157
Fury
  • 3,282
  • 3
  • 26
  • 53
82
// Swift
var titleEdgeInsets: UIEdgeInsets!

// Objective-C
@property(nonatomic) UIEdgeInsets titleEdgeInsets;

Use this property to resize and reposition the effective drawing rectangle for the button title. You can specify a different value for each of the four insets (top, left, bottom, right). A positive value shrinks, or insets, that edge—moving it closer to the center of the button. A negative value expands, or outsets, that edge. Use the UIEdgeInsetsMake function to construct a value for this property. The default value is UIEdgeInsetsZero.

https://developer.apple.com/documentation/uikit/uibutton/1624010-titleedgeinsets

pkamb
  • 26,648
  • 20
  • 124
  • 157
AechoLiu
  • 15,710
  • 9
  • 85
  • 113
  • 11
    When I use this method, it makes the text in the title label truncated in the middle. – Jeremy White Mar 03 '16 at 00:28
  • @Jeremy, you need to find another method for `UIButton` about resizing text font size when it's length is too long. For example, [this post](http://stackoverflow.com/questions/4135032/ios-uibutton-resize-according-to-text-length) – AechoLiu Mar 03 '16 at 01:11
  • But the length of the string isn't too long to fit in the available space for the UIButton. If the title needs 100px to display, setting the `titleEdgeInsets` to `(0, 10, 0, 0)` will give the title only 90px to display and truncate the text. – Jeremy White Mar 03 '16 at 17:59
  • @Jeremy, If you reduce the font size, does the problem exists ? This property is like the `margin` or `padding` in css. If the text is truncated, it is another story. – AechoLiu Mar 04 '16 at 01:03
  • 3
    The font has to be that size to match the design specs. There is plenty of horizontal space on the screen for the button, but it won't auto-grow on it's own if I set `titleEdgeInsets`. – Jeremy White Mar 04 '16 at 22:04
  • 15
    @JeremyWhite I set the *content* insets instead of the title insets in Interface Builder, and it avoids the middle truncation issue, which I was having, too. – bugloaf Apr 14 '17 at 15:06
  • using titleEdgeInsets will not evaluate the content of the insets on the intrinsic content size of the button. Better to use contentEdgeInsets https://developer.apple.com/documentation/uikit/uibutton/1624036-contentedgeinsets – Aitor Pagán Feb 15 '21 at 17:32
52

Setting the content insets will prevent the UIButton's title to shrink or truncated, giving the text margin a padding.

content edges

J. Doe
  • 9,757
  • 4
  • 42
  • 83
  • 7
    Should be voted way higher! Super simple and works with dynamic text. – Max Feb 21 '18 at 15:56
  • 1
    Simple and worked great! As an Android coder, I searched "xcode uibutton text padding" and found this. – Dale May 26 '18 at 23:45
10

The challenge with the accepted answer is that setting the titleEdgeInsets is the limitation, as noted in Apple's documentation:

This property is used only for positioning the title during layout. The >button does not use this property to determine intrinsicContentSize and >sizeThatFits(_:).

This means that setting the margins only works if the button is explicitly sized to fit the title label and the margins. If a title is too long or the margins too large, the title text may be clipped. This is OK for a button whose title you know at compile time, but for a variable length button title, can pose a problem.

An alternate approach accommodating variable title length is to leave the titleEdgeInsets as the default value. Once the button's title is set, add explicit width and height constraints that accommodate the button's title label and the additional margins. For example:

let margin: CGFloat = 10.0

let button = UIButton()

button.setTitle("My Button Title", for .normal)

button.widthAnchor.constraint(equalToConstant: button.titleLabel!.intrinsicContentSize.width + margin * 2.0).isActive = true

button.heightAnchor.constraint(equalToConstant: button.titleLabel!.intrinsicContentSize.height + margin * 2.0).isActive = true

Position the button without adding further height or width constraints and it will appear properly regardless of title length.

user3847320
  • 734
  • 6
  • 16
  • Is there a typo on the second line of code? Should it be intrinsicContentSize.height instead of intrinsicContentSize.width? – Michael Peterson Oct 24 '17 at 17:14
  • Objective-C version: `[button.widthAnchor constraintEqualToConstant:button.titleLabel.intrinsicContentSize.width + margin * 2.0].active = YES;` – Stunner Jan 07 '18 at 05:56
8

In Swift 4, note the use of contentEdgeInsets not titleEdgeInsets:

btn.contentEdgeInsets =  UIEdgeInsetsMake(8, 8, 8, 8)
btn.titleLabel?.lineBreakMode = .byWordWrapping

That will make the button wrap its text and keep it one line as long as there is a space for it + adding some padding around

pkamb
  • 26,648
  • 20
  • 124
  • 157
Daniel Raouf
  • 1,919
  • 1
  • 17
  • 24
5

This option is also viable if its not too annoying to use a UIButton subclass

class Button: UIButton {
    override var intrinsicContentSize: CGSize {
        get {
            let baseSize = super.intrinsicContentSize
            return CGSize(width: baseSize.width + titleEdgeInsets.left + titleEdgeInsets.right,
                          height: baseSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom)
        }
    }
}

Then use titleEdgeInsets as desired

 let button = Button()
 ... configure button
 button.titleEdgeInsets = ...
wfbarksdale
  • 6,962
  • 11
  • 60
  • 87
5

With the above solutions, some of the text were cut out if you have a border around the button. For instance, a button label named "Delete something" ends up showing "Dele...ing". If you are having this problem, this is the solution:

aButton.contentEdgeInsets = UIEdgeInset.init(top: 0, left: 8, bottom: 0, right: 8)
Joseph Francis
  • 825
  • 1
  • 13
  • 20
3

The contentHorizontalAlignment property works like a charm, as explained here:

How to set the title of UIButton as left alignment?

pkamb
  • 26,648
  • 20
  • 124
  • 157
1

I found an easy/hacky way to add borders to text buttons (and have left/right margins):

  1. Create button with title.

  2. Place button in storyboard, align where you want and then add a forced width constraint that is an even number (I used 20, so it adds 10 points on each side). This will force the border around the width you created.

  3. Use code to create a border. eg:

    myTextButton.backgroundColor = .clear
    myTextButton.layer.cornerRadius = 5
    myTextButton.layer.borderWidth = 2
    myTextButton.layer.borderColor = UIColor.white.cgColor
    
  4. Set left titleInset to 2 via editor (now under Size Inspector) or by code. This seems to center the text, but this value may be different for various texts and text sizes.

This post is for Xcode 8.1 and Swift 3.

pkamb
  • 26,648
  • 20
  • 124
  • 157
Abhi
  • 240
  • 1
  • 12
0

As Apple recommends:

https://developer.apple.com/documentation/uikit/uibutton/1624036-contentedgeinsets

Use contentEdgeInsets

Use this property to resize and reposition the effective drawing rectangle for the button content. The content comprises the button image and button title. You can specify a different value for each of the four insets (top, left, bottom, right). A positive value shrinks, or insets, that edge—moving it closer to the center of the button. A negative value expands, or outsets, that edge. Use the init(top:left:bottom:right:) function to construct a value for this property. The default value is zero.

The button uses this property to determine intrinsicContentSize and sizeThatFits(_:).

Swift

aButton.contentEdgeInsets = UIEdgeInsets(top: YOURVALUE, left: YOURVALUE, bottom: YOURVALUE, right: YOURVALUE)
Aitor Pagán
  • 423
  • 5
  • 17