Reputation: 2839
I have the following layout, and I'm trying to add a padding to the left and right..
The controls are a disabled UIButton.
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];
Upvotes: 77
Views: 67761
Reputation: 131
iOS 15+ Solution
All 3 edge inset methods on UIButton
(title, content, image) have been deprecated as of iOS 15. The current recommendation is to use UIButton.Configuration
.
Here is how you'd add content insets to a button using UIButton.Configuration
:
// Initialize your button as you normally would
let button = UIButton(type: .custom, primaryAction: UIAction(title: "") { _ in
// your action handler
})
// Create a mutable configuration instance using a predefined factory method.
// Check out the documentation for factory methods other than .plain()
// --> https://developer.apple.com/documentation/uikit/uibutton/configuration/#3813731
var configuration = UIButton.Configuration.plain()
// Set your insets on the configuration object
let contentOffset: CGFloat = 5
configuration.contentInsets = .init(top: contentOffset, leading: contentOffset, bottom: contentOffset, trailing: contentOffset)
// And finally, assign the configuration to the button to update it.
button.configuration = configuration
Note that once you use a Configuration
object on a UIButton
, you will need to use it to configure everything else on the button. For instance, to set a custom font, you'll be no longer able to set the font directly on UIButton.titleLabel
but you'll need to set it via UIButton.Configuration.attributedTitle
like so:
configuration.attributedTitle = AttributedString("Button Title",
attributes:
AttributeContainer([
NSAttributedString.Key.font : UIFont.systemFont(ofSize: 12),
NSAttributedString.Key.foregroundColor : .black
]))
Hope this helps!
Upvotes: 1
Reputation: 18428
// 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
titleEdgeInsets is deprecated in iOS 15.0.
Upvotes: 83
Reputation: 13103
Setting the content insets will prevent the UIButton
's title to shrink or truncated, giving the text margin a padding.
Storyboard
Code
someButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5
Upvotes: 63
Reputation: 423
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)
Upvotes: 0
Reputation: 3442
You can also set the inset values from the Interface Builder Size Inspector inside a Storyboard or xib.
Upvotes: 99
Reputation: 153
The contentHorizontalAlignment
property works like a charm, as explained here:
How to set the title of UIButton as left alignment?
Upvotes: 3
Reputation: 270
I found an easy/hacky way to add borders to text buttons (and have left/right margins):
Create button with title.
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.
Use code to create a border. eg:
myTextButton.backgroundColor = .clear
myTextButton.layer.cornerRadius = 5
myTextButton.layer.borderWidth = 2
myTextButton.layer.borderColor = UIColor.white.cgColor
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.
Upvotes: 1
Reputation: 2357
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
Upvotes: 13
Reputation: 1231
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)
Upvotes: 6
Reputation: 822
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.
Upvotes: 9
Reputation: 7606
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 = ...
Upvotes: 6