Skip to content

BlogLabels with padding in iOS

Labels with padding in iOS

archivelabelsnapkitiosswift

There is no standard way of creating UILabels with padding around the text in iOS. And usually that’s not really necessary because you should be using auto layout to position the label and the space around them. However, there are some occasions when you have a UILabel and just need some padding around it. One such occasion would be the creation of table view headers. Instead of manually creating a UIView around a UILabel to achieve this let’s have a look at some alternatives.

Specifying the padding

First let’s see what a good way of specifying padding is. For UIButtons you can do this by setting its content inset with a UIEdgeInsets value. So it appears that UIEdgeInsets is the right choice for specifying padding. How can we use that on a UILabel?

The easy way, use SnapKit

By far the easiest way of achieving what we want is through the usage of the SnapKit library.

let label = UILabel()
label.text = "Hello label"

let padding = UIEdgeInsets(top: 4, left: 12, bottom: 4, right: 12)

let container = UIView()
container.addSubview(label)
label.snp_makeConstraints { make in
make.edges.equalTo(container).inset(padding)
}

// container is now our label with padding, though
// it's not a UILabel itself

As we can see, SnapKit makes it really easy and by using constraints, our container view will also automatically have an intrinsic content size that’s equal to the intrinsic content size of the label + the padding.

But to write the above code each time we need a label with padding would still be less than ideal. Let’s improve that.

UIView extension

The above code snippet does not only work on UILabels but on any UIView. So let’s add an extension to UIView that makes it really easy to add padding.

extension UIView {

  func withPadding(padding: UIEdgeInsets) -> UIView {
    let container = UIView()
    container.addSubview(self)
    snp_makeConstraints { make in
      make.edges.equalTo(container).inset(padding)
    }
    return container
  }
}

We can now use this as follows:

let label = UILabel()
label.text = "Hello label"

let padding = UIEdgeInsets(top: 4, left: 12, bottom: 4, right: 12)
let labelWithPadding = label.withPadding(padding)

Just keep in mind that it doesn’t add padding to the existing UILabel but that it’s returning a new UIView instead.

Often I even add a convenience initializer with the text to UILabel through an extension:

extension UILabel {
  convenience init(text: String) {
    self.init()
    self.text = text
  }
}

Now we can put it all in a nice one-liner that everyone loves so much:

let label = UILabel(text: "Hello label")
  .withPadding(UIEdgeInsets(top: 4, left: 12, bottom: 4, right: 12))

This makes it a lot easier to return table view headers that need to be just text, like the standard ones, but with a little bit of extra padding.

Without SnapKit

For those who don’t want to include SnapKit into their project only to create some labels, it’s not that hard to do it manually.

You can do it either by creating the constraints yourself or through the visual formatting like this:

extension UIView {
  func withPadding(padding: UIEdgeInsets) -> UIView {
    let container = UIView()
    self.translatesAutoresizingMaskIntoConstraints = false
    container.addSubview(self)
    container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
      "|-(\(padding.left))-[view]-(\(padding.right))-|"
      , options: [], metrics: nil, views: ["view": self]))
    container.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
      "V:|-(\(padding.top))-[view]-(\(padding.bottom))-|",
      options: [], metrics: nil, views: ["view": self]))
    return container
  }
}

Comparing this to the SnapKit example you can see why I prefer to use SnapKit