0

I have a View where I create a UILabel with numberOfLines equal to zero. I want the label size to be adjusted according to the content of my label (according to numberOfLines). However, I have tried many things including all this, and it still does not work for me. I use Neon library for AutoLayot.

And here's my whole for View:

import UIKit
import Neon

class AdditionalDescriptionView: UIView {

    lazy var locationLabel = UILabel()
    lazy var seasonLabel = UILabel()
    lazy var quantityLabel = UILabel()
    lazy var durationLabel = UILabel()
    lazy var requirementsLabel = UILabel()
    var height: CGFloat = 0
    var text = NSString()
    var size = CGSize()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setup() {
        locationLabel.textAlignment = .left
        locationLabel.text = "Локация: Каркаралинск (200км от Караганды)"
        locationLabel.textColor = .black
        locationLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        locationLabel.numberOfLines = 0
        seasonLabel.textAlignment = .left
        seasonLabel.textColor = .black
        seasonLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        seasonLabel.text = "Сезоны: все"
        quantityLabel.textAlignment = .left
        quantityLabel.textColor = .black
        quantityLabel.text = "Количество людей: 5-25"
        quantityLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        durationLabel.textAlignment = .left
        durationLabel.textColor = .black
        durationLabel.text = "Длительность тура: 3 суток"
        durationLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        requirementsLabel.textAlignment = .left
        requirementsLabel.textColor = .black
        requirementsLabel.text = "Требования: удобная обувь, дополнительный груз не более 3кг, минимум 1л питьевой воды. Лицам с кардио- и дыхательными проблемами не рекомендуется участие в туре."
        requirementsLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        requirementsLabel.numberOfLines = 0
        requirementsLabel.lineBreakMode = .byWordWrapping
        requirementsLabel.sizeToFit()

        self.addSubview(locationLabel)
        self.addSubview(seasonLabel)
        self.addSubview(quantityLabel)
        self.addSubview(durationLabel)
        self.addSubview(requirementsLabel)

        updateConstraints()
    }

    override func updateConstraints() {
        locationLabel.anchorToEdge(.top, padding: 0, width: self.frame.width, height: AutoHeight)
        seasonLabel.align(.underCentered, relativeTo: locationLabel, padding: 0, width: self.frame.width, height: AutoHeight)
        seasonLabel.alignAndFillWidth(align: .underCentered, relativeTo: locationLabel, padding: 0, height: AutoHeight)
        quantityLabel.alignAndFillWidth(align: .underCentered, relativeTo: seasonLabel, padding: 0, height: AutoHeight)
        durationLabel.alignAndFillWidth(align: .underCentered, relativeTo: quantityLabel, padding: 0, height: AutoHeight)
        // fix requirementsLabel height
        requirementsLabel.alignAndFillWidth(align: .underCentered, relativeTo: durationLabel, padding: 0, height: AutoHeight)
        height = locationLabel.frame.height+seasonLabel.frame.height+quantityLabel.frame.height+durationLabel.frame.height+requirementsLabel.frame.height
    }
}

using this for actually adding the view:

self.view.addSubview(additional)
additional.anchorAndFillEdge(.top, xPad: 0, yPad: 0, otherSize: additional.height)
additional.updateConstraints()
Community
  • 1
  • 1
Anuar Maratkhan
  • 325
  • 5
  • 21
  • I'm having a hard time understanding what you're actually trying to accomplish but right off the bat I see something that is definitely wrong. `height: requirementsLabel.frame.size.height` makes no sense because that parameter is a constant. You're passing in the constant height you got from `sizeToFit` so it will not adjust for any other changes after the fact. – Dima Feb 18 '17 at 20:29
  • @Dima I actually have been using `AutoHeight` property of *Neon* library that "should" adjust the size automatically. However, it gives me only one line size. So, I just hadn't paid so much attention what I write there because that's the property that I need to find out. – Anuar Maratkhan Feb 18 '17 at 20:33
  • I looked it up and I see `AutoHeight`. Still not sure about the answer to your question without some more details but you should edit your question to have exactly the code that you're using. – Dima Feb 18 '17 at 20:54
  • @Dima I have added whole code for that View – Anuar Maratkhan Feb 18 '17 at 21:00
  • I'll try to help you. What is the actual behavior you are seeing happening? – Dima Feb 18 '17 at 21:11
  • @Dima I see that my `requirementsLabel` goes out of the actual *View* because AutoHeight counts only the first line's size as a whole size of label. So, other lines just fall out of my view. – Anuar Maratkhan Feb 18 '17 at 21:17
  • Your problem is occurring somewhere else. I just copy pasted your code into a new project by adding the view to a view controller and it works just fine for me, screenshot: http://take.ms/QVQug So the problem is most likely how you are actually adding and using `AdditionalDescriptionView`. The internals are fine. – Dima Feb 18 '17 at 21:23
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/136050/discussion-between-anuar-maratkhan-and-dima). – Anuar Maratkhan Feb 18 '17 at 21:44

1 Answers1

1

I gave up trying to solve this using Neon. The problem was essentially that you were trying to define a concrete height for your container view while at the same time trying to anchor the elements within it to each other and its margins. I ended up just using the standard Auto Layout API using layout anchors. Then, all you need to do is specify the width of your container and its height will be set up automatically based on the size of the labels it contains. The solution is as follows:

import UIKit

class AdditionalDescriptionView: UIView {

    lazy var locationLabel = UILabel()
    lazy var seasonLabel = UILabel()
    lazy var quantityLabel = UILabel()
    lazy var durationLabel = UILabel()
    lazy var requirementsLabel = UILabel()
    var text = NSString()
    var size = CGSize()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setup() {
        self.translatesAutoresizingMaskIntoConstraints = false
        backgroundColor = UIColor.blue
        locationLabel.textAlignment = .left
        locationLabel.text = "Локация: Каркаралинск (200км от Караганды)"
        locationLabel.textColor = .black
        locationLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        locationLabel.numberOfLines = 0
        seasonLabel.textAlignment = .left
        seasonLabel.textColor = .black
        seasonLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        seasonLabel.text = "Сезоны: все"
        quantityLabel.textAlignment = .left
        quantityLabel.textColor = .black
        quantityLabel.text = "Количество людей: 5-25"
        quantityLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        durationLabel.textAlignment = .left
        durationLabel.textColor = .black
        durationLabel.text = "Длительность тура: 3 суток"
        durationLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        requirementsLabel.textAlignment = .left
        requirementsLabel.textColor = .black
        requirementsLabel.text = "Требования: удобная обувь, дополнительный груз не более 3кг, минимум 1л питьевой воды. Лицам с кардио- и дыхательными проблемами не рекомендуется участие в туре."
        requirementsLabel.font = UIFont.avenirNextRegular(ofSize: 14)
        requirementsLabel.numberOfLines = 0
        requirementsLabel.lineBreakMode = .byWordWrapping

        self.addSubview(locationLabel)
        locationLabel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(seasonLabel)
        seasonLabel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(quantityLabel)
        quantityLabel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(durationLabel)
        durationLabel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(requirementsLabel)
        requirementsLabel.translatesAutoresizingMaskIntoConstraints = false

        locationLabel.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        seasonLabel.topAnchor.constraint(equalTo: locationLabel.bottomAnchor).isActive = true
        quantityLabel.topAnchor.constraint(equalTo: seasonLabel.bottomAnchor).isActive = true
        durationLabel.topAnchor.constraint(equalTo: quantityLabel.bottomAnchor).isActive = true
        requirementsLabel.topAnchor.constraint(equalTo: durationLabel.bottomAnchor).isActive = true
        requirementsLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

        locationLabel.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        seasonLabel.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        quantityLabel.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        durationLabel.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
        requirementsLabel.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true

        locationLabel.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        seasonLabel.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        quantityLabel.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        durationLabel.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
        requirementsLabel.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
    }
}


class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let additional = AdditionalDescriptionView()
        self.view.addSubview(additional)
        additional.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
        additional.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
    }
}
Dima
  • 23,484
  • 6
  • 56
  • 83