swift: programmatically create UILabel fixed width that resizes vertically according to text length

后端 未结 2 917
攒了一身酷
攒了一身酷 2021-02-20 14:09

I\'ve seen answers to vertical resizing that involve autolayout, but the UILabels I\'m creating are only needed at runtime. (I might need anywhere from zero to many

相关标签:
2条回答
  • 2021-02-20 14:31

    Set the label's numberOfLines property to zero and fix the width of your labels with constraints (either by constraining the width explicitly or by constraining the leading and trailing edges to some other view like the label's superview). Then the labels will resize vertically automatically to the height that fits the text. You'll need to pin one label via its top constraint so the view system knows where to start the layout, then the top of all your other labels should be constrained to the bottom of the previous label. This way they will all layout relative to the height of the previous label.

    edit in response to your comment:

    You can set the width of a view explicitly on iOS 9 and later by using the widthAnchor property. You can set it on older iOS versions using NSLayoutConstraints (search SO for examples).

    e.g.:

    label.widthAnchor.constraintEqualToConstant(50.0).active = true

    This would set the label's width to 50 points wide, but not fix its height, so with numberOfLines = 0 then the label will auto-resize vertically when you set the text.

    0 讨论(0)
  • 2021-02-20 14:45

    There are two usefull methods of UIView: sizeToFit() and sizeThatFits(_:)

    The first one resizes a view to a minimal size to fit subviews' content and the second one doesn't change frame at all, but returns calculated size which: (1) fit all subviews and (2) doesn't exceed parameter size

    So you can use sizeThatFits for you purpose:

    let label = UILabel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        label.backgroundColor = UIColor.orange
        label.textColor = UIColor.white
    //  label.text = "ultimate Frisbee"
        label.text = "ultimate Frisbee\nin 3 minutes,\nall welcome|2"
        label.numberOfLines = 10
        view.addSubview(label)
    
        updateLabelFrame()
    }
    
    func updateLabelFrame() {
        let maxSize = CGSize(width: 150, height: 300)
        let size = label.sizeThatFits(maxSize)
        label.frame = CGRect(origin: CGPoint(x: 100, y: 100), size: size)
    }
    

    Output:

    P.S. You also can solve your problem with autolayout constraints, but I am not a big fan of using them programmatically.

    0 讨论(0)
提交回复
热议问题