Home > database >  How to create a custom UIView with a subview inside, setting its size/position with AutoLayout progr
How to create a custom UIView with a subview inside, setting its size/position with AutoLayout progr

Time:03-11

I would like to create a custom UIView, say TestLabelView, which contains a label whose margin would be 16px.

It would look like this:

enter image description here

Here is how I tried to create this custom UIView and instantiated it in a view controller:

TestLabelView

class TestLabelView: UIView {
    private var label = UILabel()
    
    var text: String = "" { didSet { updateUI() } }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        internalInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        internalInit()
    }
    
    private func internalInit() {
        backgroundColor = .red
        label.numberOfLines = 0
        translatesAutoresizingMaskIntoConstraints = false
        addSubview(label)
    }
    
    private func updateUI() {
        label.text = text
        NSLayoutConstraint(item: label,
                           attribute: .leading,
                           relatedBy: .equal,
                           toItem: self,
                           attribute: .leading,
                           multiplier: 1,
                           constant: 24).isActive = true
        NSLayoutConstraint(item: self,
                           attribute: .trailing,
                           relatedBy: .equal,
                           toItem: label,
                           attribute: .trailing,
                           multiplier: 1,
                           constant: 24).isActive = true
        NSLayoutConstraint(item: label,
                           attribute: .top,
                           relatedBy: .equal,
                           toItem: self,
                           attribute: .top,
                           multiplier: 1,
                           constant: 24).isActive = true
        NSLayoutConstraint(item: self,
                           attribute: .bottom,
                           relatedBy: .equal,
                           toItem: label,
                           attribute: .bottom,
                           multiplier: 1,
                           constant: 24).isActive = true
        setNeedsUpdateConstraints()
    }
}

ViewController

class ViewController: UIViewController {
    @IBOutlet weak var testLabelView: TestLabelView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        testLabelView?.text = "This is a test view with a test label, contained in multiple lines"
    }
}

In the storyboard

enter image description here

I have set a placeholder intrinsic size to remove the storyboard error, and the bottom margin is greater than or equal to 24px, so the view height should be set depending on the content size

However by doing so, I don't see the label appearing. What am I doing wrong?

enter image description here

Thank you for your help

CodePudding user response:

You can try this code for your TestLabelView view

class TestLabelView: UIView {
    private var label : UILabel = {
        let l = UILabel()
        l.translatesAutoresizingMaskIntoConstraints = false
        l.numberOfLines = 0
        return l
    }()
    
    var text: String = "" { didSet { self.label.text = self.text } }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        internalInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        internalInit()
    }
    
    private func internalInit() {
        backgroundColor = .red
        translatesAutoresizingMaskIntoConstraints = false
        addSubview(label)
        setConstraints()
    }
    
    private func setConstraints() {
        NSLayoutConstraint.activate([
            self.label.topAnchor.constraint(equalTo: self.topAnchor, constant: 16),
            self.label.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 16),
            self.label.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -16),
            self.label.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -16),
        ])
    }
}
  • Related