3

I am wanting to create a label programmatically that is able to word wrap for long sentences. Here is the loop I have for creating the labels:

        for i in 0..<servicesLength
    {
        let label = UILabel(frame: CGRectMake(0, number, servicesScroll.bounds.size.width - 42, 25))
        label.lineBreakMode = .ByWordWrapping
        label.numberOfLines = 0
        label.font = UIFont(name: label.font.fontName, size: 25)
        label.text = servicesList[i]
        self.servicesScroll.addSubview(label)
        number = number + 50

    }

This doesnt work though. From what I've read, in order for the wrapping to work, you need to either not set the height or make the height large enough for the content. I have to set the height for the frame and I don't want to make it extremely large for large sentences so how can I get this to work by setting everything programmatically?

user1715916
  • 321
  • 5
  • 12
  • So I have it working except it seems to throws things off by adjusting the height of the label. It pushes all of the labels down by the same amount I change the height to. This causes lots of white space at the top and some of the labels to go past the bottom of the scrollview. What can I do to fix this? – user1715916 Sep 20 '16 at 21:02

2 Answers2

3

Why not using Autolayout, this will also let you support the orientation change on the devices.

    var lastLabel:UILabel?

    for i in 0..<10servicesLength
    {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints=false
        label.lineBreakMode = .ByWordWrapping
        label.numberOfLines = 10
        label.font = UIFont(name: label.font.fontName, size: 25)
        label.text = servicesList[i]
        servicesScroll.addSubview(label)

        let metrics=["horizontalMargin":21,"top":0,"bottom":0,"separationBetweenLabels":0,"labelMinHeight":25]
        let views=["label":label]

        servicesScroll.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-horizontalMargin-[label]-horizontalMargin-|",
            options: NSLayoutFormatOptions(rawValue: 0),
            metrics: metrics,
            views: views))

        if i == 0{
            servicesScroll.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-top-[label]",
                options: NSLayoutFormatOptions(rawValue: 0),
                metrics: metrics,
                views: views))
        }
        if let lastLabel=lastLabel{
            views["lastLabel"]=lastLabel
            servicesScroll.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[lastLabel]-separationBetweenLabels-[label]",
                options: NSLayoutFormatOptions(rawValue: 0),
                metrics: metrics,
                views: views))
        }
        if i == (servicesLength-1){
            servicesScroll.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[label]-bottom-|",
                options: NSLayoutFormatOptions(rawValue: 0),
                metrics: metrics,
                views: views))
        }

        //Optional a minimum height of 25
        servicesScroll.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[label(>=labelMinHeight)]",
            options: NSLayoutFormatOptions(rawValue: 0),
            metrics: metrics,
            views: views))

        lastLabel=label
    }

The important part is that you set the numberOfLines of each label as the maximum size that you will allow the label to grow.

Also I add a constraint for a miminum height:

    //Optional a minimum height of 25
    servicesScroll.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[label(25)]",
        options: NSLayoutFormatOptions(rawValue: 0),
        metrics: metrics,
        views: views))

This will guarantee that the label will be at least 25 height and maximum of 10 lines in this example.

omarzl
  • 560
  • 4
  • 9
  • Thanks for your post. I didn't want to support horizontal orientation because the app wouldn't look good in landscape. I was trying to avoid hard coding in a max height situation. I was hoping that I could just get it to wrap the lines until it was finished. I have some strings that are about a paragraph long and others just a sentence. I tried out your code and your missing something that tells where the initial start point of the label is so they are all placed on top of each other. – user1715916 Sep 20 '16 at 13:06
  • So I tried increasing the height and the space between the labels which did allow them to show up but I get alot of empty space at the top before the first label. The space seems to be equal to the height I put in for the labels. Everything looks great except for the chunk of space. How do I get rid of this? – user1715916 Sep 20 '16 at 18:03
  • Sorry, there were errors in my code, I updated it. Please check it again and you should have no problem with the space at the top. – omarzl Sep 21 '16 at 14:29
0

I decided on using a TableView instead. It gave me exactly what I was looking for. If you are needing a list of sentences displayed and need word wrap for possibly large sentences or paragraphs, a tableview is much easier than messing around with adding labels programmatically. Here are the steps I followed:

  1. Follow this tutorial on how to make a tableview in Swift.
  2. Add cell.textLabel?.numberOfLines = 0 to the function that creates the cells in order to get word wrap.
  3. Add yourtableview.estimatedRowHeight = whateveryouwant yourtableview.rowHeight = UITableViewAutomaticDimension in your viewDidLoad in order to get variable heights for your rows.
Community
  • 1
  • 1
user1715916
  • 321
  • 5
  • 12