Using UIEdgeInsets to layout a UIButton
You can use insets to layout the content of system or custom buttons. With insets you can add or remove space to the button’s title (titleEdgeInsets), image (imageEdgeInsets) and both the title and image together (contentEdgeInsets).
To see how these three properties work, create a button (UIButton) via a xib-file or in code. Give it only a center vertically and horizontally in superview constraint, but not a width constraint for this first example. Give the contentView a blue background color, the imageView a red background color and the titleLabel a yellow background color. On top of that you can also give the border of the button a green color.
button.backgroundColor = .blue
button.imageView?.backgroundColor = .red
button.titleLabel?.backgroundColor = .yellow
button.layer.borderColor = UIColor.green.cgColor
button.layer.borderWidth = 2
The contentEdgeInsets is behaving as you might expect. You can add space around both the imageView and titleLabel by using positive values.
let spacing: CGFloat = 8.0
button.contentEdgeInsets = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: spacing)
The rule when it comes to titleEdgeInsets or imageEdgeInsets is to add equal and opposite offsets to the left and right insets. So if you add for example 8 points to the left title inset, you need to apply -8 points to the right inset. In this way you use the insets only to offset the title or image and not to resize them in any way. If you don’t do this, the calculated layout rect may become too small and the title can be truncated and the spacing will show some weird behaviour.
button.titleEdgeInsets = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: 0)
To flip the title with the image we can use the imageEdgeInsets and titleEdgeInsets to move the imageView behind the titleLabel. First we move the imageView the same amount as the button width to the right and then we subtract the amount of the image width so that the imageView will stay in the content-view. It will look like this:
We set the opposite value of the left inset for the right inset:
let buttonWidth = button.frame.width
let imageWidth = button.imageView!.frame.width