I'm building a screen to scan barcodes, and I need to put a translucent screen behind some UILabels
to improve visibility against light backgrounds.
Here's what the screen looks like now:
I'm setting the background color on the UILabel
to get the translucent boxes. I've also created a custom UILabel
subclass to allow me to set some padding between the edge of the UILabel
and the text using this approach.
As you can see in the screen above, the UILabel
doesn't resize correctly to take the padding into account. The "padding" just shifts the text over without changing the width of the label, causing the text to truncate.
Both of these labels will contain text of arbitrary lengths, and I really need the UILabel
to dynamically resize.
What UILabel
method can I override to increase the width of the label and factor in the padding?
Here's a label class that calculates sizes correctly. The posted code is in Swift 3, but you can also download Swift 2 or Objective-C versions.
By calculating the proper textRect all of the sizeToFit
and auto layout stuff works as expected. The trick is to first subtract the insets, then calculate the original label bounds, and finally to add the insets again.
class NRLabel: UILabel { var textInsets = UIEdgeInsets.zero { didSet { invalidateIntrinsicContentSize() } } override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect { let insetRect = bounds.inset(by: textInsets) let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines) let invertedInsets = UIEdgeInsets( top: -textInsets.top, left: -textInsets.left, bottom: -textInsets.bottom, right: -textInsets.right ) return textRect.inset(by: invertedInsets) } override func drawText(in rect: CGRect) { super.drawText(in: rect.inset(by: textInsets)) } }
If you want to setup text insets in storyboards you can use the following extension to enable Interface Builder support:
@IBDesignable extension NRLabel { // currently UIEdgeInsets is no supported IBDesignable type, // so we have to fan it out here: @IBInspectable var leftTextInset: CGFloat { set { textInsets.left = newValue } get { return textInsets.left } } // Same for the right, top and bottom edges. }
Now you can conveniently setup your insets in IB and then just press ⌘= to adjust the label's size to fit.
All code is in the public domain. Do as you please.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With