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()
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
}
}