In this episode we create some more custom @IBDesignable views, this time for a padded genre label where we use the intrinsicContentSize to make a label take up more space and give itself a little padding. We also create a separator view that draws a thin line to separate sections visually.
Padded Label and Separator View In this episode, we create some more custom @IBDesignable views, this time for a padded genre label where we use the intrinsicContentSize to make a label take up more space and give itself a little padding. We also create a separator view that draws a thin line to separate sections visually. Creating Custom Genre Label We will start by creating a custom UILabel to define our settings. To view the custom label rendered in Interface Builder, we will mark the class as @IBDesignable and configure the UI components with @IBInspectable. Since the content size is dependent on these properties, we need to invalidate the intrinsic content size in didSet. import UIKit @IBDesignable class GenreLabel : UILabel { @IBInspectable var horizontalInset: CGFloat = 0 { didSet { invalidateIntrinsicContentSize() } } @IBInspectable var verticalInset: CGFloat = 0 { didSet { invalidateIntrinsicContentSize() } } } Now we will set properties for the label. We will set cornerRadius to half of bounds height and to see the effect of this setting we will set masksToBounds. Now we will define intrinsicContentSize. private func commonSetup() { backgroundColor = Theme.Colors.gray2 textColor = Theme.Colors.gray0 font = UIFont.systemFont(ofSize: 12, weight: .medium) textAlignment = .center layer.masksToBounds = true } override func layoutSubviews() { super.layoutSubviews() layer.cornerRadius = bounds.size.height / 2 } override var intrinsicContentSize: CGSize { var superSize = super.intrinsicContentSize superSize.width += horizontalInset * 2 superSize.height += verticalInset * 2 return superSize } Creating a Separator View We will create a UIView by marking it with @IBDesignable and its properties marked with @IBInspectable. To trigger the setting of separatorColor through Interface Builder we need to call setNeedsDisplay while setting this property. @IBDesignable class SeparatorView : UIView { @IBInspectable var separatorColor: UIColor = Theme.Colors.gray3 { didSet { setNeedsDisplay() } } override func awakeFromNib() { super.awakeFromNib() commonSetup() } override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() commonSetup() } } We will now draw the separator view and set the properties for the current context. To draw the separator at the mid-level of original, set y to half of the height. To ensure visibility of our custom settings, set the properties like isOpaque and backgroundColor. private func commonSetup() { isOpaque = false backgroundColor = .clear } override func draw(_ rect: CGRect) { guard let context = UIGraphicsGetCurrentContext() else { return } separatorColor.setStroke() context.setLineWidth(1/UIScreen.main.scale) let midY = bounds.size.height / 2 context.move(to: CGPoint(x: 0, y: midY)) context.addLine(to: CGPoint(x: bounds.size.width, y: midY)) context.strokePath() }