Search code examples
swift3uilabelword-wrap

Can't get UILabel to word wrap


I have used Interface Builder to get UILabelViews to word wrap, but this is my first attempt to do it programmatically. I believe the issue is that although I'm setting:

label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0

I'm setting a line height which might conflict with these properties?

override func layoutSubviews() {
    super.layoutSubviews()
    imageViewContent.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
    imageViewContent.loadImageWithURL(imageName!)

    label.frame = CGRect(x: 0, y: 0, width: frame.size.width-10, height: 21)
    label.center = imageViewContent.center
    label.textAlignment = .center
    label.clipsToBounds = true
    label.layer.cornerRadius = 10.0
    label.textColor = .white
    label.font = UIFont(name: "AvenirNext-DemiBold", size: 15)
    label.backgroundColor = UIColor.black.withAlphaComponent(0.5)
    label.lineBreakMode = .byWordWrapping
    label.numberOfLines = 0
    label.text = photoName
}

Solution

  • As I suspected, hardcoding the height of the label prevented it from word wrapping. I've created a labelHeight variable and added a function at the bottom of the class to calculate the labelHeight based on the content, font size, and labelWidth I set. Code works fine now:

     class NTWaterfallViewCell :UICollectionViewCell, NTTansitionWaterfallGridViewProtocol{
    
            var photoName = ""
            var imageName : String?
            var labelHeight: CGFloat = 0.0
    
            var imageViewContent : UIImageView = UIImageView()
            var label = UILabel()
    
            required init?(coder aDecoder: NSCoder) {
                fatalError("init(coder:) has not been implemented")
            }
            override init(frame: CGRect) {
                super.init(frame: frame)
                backgroundColor = UIColor.lightGray
                contentView.addSubview(imageViewContent)
                contentView.addSubview(label)
            }
            override func layoutSubviews() {
                super.layoutSubviews()
                imageViewContent.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
                imageViewContent.loadImageWithURL(imageName!)
    
                label.text = photoName
                labelHeight = heightForText(photoName, width: frame.size.width-10)
                label.frame = CGRect(x: 0, y: 0, width: frame.size.width-10, height: labelHeight)
    
                label.center = imageViewContent.center
                label.textAlignment = .center
                label.clipsToBounds = true
                label.layer.cornerRadius = 10.0
                label.textColor = .white
                label.font = UIFont(name: "AvenirNext-DemiBold", size: 15)
                label.backgroundColor = UIColor.black.withAlphaComponent(0.5)
                label.lineBreakMode = .byWordWrapping
                label.numberOfLines = 0
                }
    
            func heightForText(_ text: String, width: CGFloat) -> CGFloat {
                let font = UIFont(name: "AvenirNext-DemiBold", size: 15)
                let rect = NSString(string: text).boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
                return ceil(rect.height)
            }
     }