Reputation: 113
I tried to use sizeToFit to let the UILabel height is dynamically change as the text. However, it do count "\n", but it seems not counting long word wrapping to new line. The text will eventually overflow.
In the code, I first add a scrollview and a stackview, and create two functions to setup their constraint and background color. When everything is done, I tried to write a for-loop, creating UIView with UILabel, and using
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.byWordWrapping
to let long word wrapped. And I create a for-loop to get longer string.
label.text = "This is first line and it is very very long long long."
for _ in 0...i{
label.text! += "\n"+"This is new added line and is also very very long long long"
}
The original code is as below if needed.
I can't figure out which step is going wrong.
Thanks for helping me.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red: 213/255, green: 165/255, blue: 68/255, alpha: 1)
//scroll and stack view adjust
let scrollView = UIScrollView()
scrollViewAdjust(scrollView: scrollView)
let stackView = UIStackView()
stackViewAdjust(stackView: stackView, scrollView: scrollView)
for i in 0..<5{
let newView = UIView()
stackView.addArrangedSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
newView.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1)
newView.layer.cornerRadius = 5
let label = UILabel()
newView.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.text = "This is first line and it is very very long long long."
for _ in 0...i{
label.text! += "\n"+"This is new added line and is also very very long long long"
}
label.topAnchor.constraint(equalTo: newView.topAnchor).isActive = true
label.leadingAnchor.constraint(equalTo: newView.leadingAnchor, constant: 3).isActive = true
label.trailingAnchor.constraint(equalTo: newView.trailingAnchor, constant: 3).isActive = true
label.sizeToFit()
print(label.frame.size.height)
newView.heightAnchor.constraint(equalToConstant: label.frame.size.height).isActive = true
}
}
//functions
func scrollViewAdjust(scrollView: UIScrollView){
view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 6).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
}
func stackViewAdjust(stackView:UIStackView, scrollView:UIScrollView){
stackView.axis = .vertical
stackView.spacing = 20
scrollView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 0.8).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 15).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
}
}
Upvotes: 0
Views: 678
Reputation: 1414
You must set a label width when you create it. I've updated the for loop from your example here to match the width of your stackView:
for i in 0..<5{
let newView = UIView()
stackView.addArrangedSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
newView.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1)
newView.layer.cornerRadius = 5
stackView.layoutIfNeeded() // needed to force update the layout before getting the width
let width = stackView.frame.width
print(width)
let label = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
newView.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.textColor = UIColor.black
label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.text = "This is \(i) line and it is very very long long long."
for ii in 0...i{
label.text! += "\n"+"This is new added \(ii) line and is also very very long long long"
}
label.sizeToFit()
label.topAnchor.constraint(equalTo: newView.topAnchor).isActive = true
label.leadingAnchor.constraint(equalTo: newView.leadingAnchor, constant: 3).isActive = true
label.trailingAnchor.constraint(equalTo: newView.trailingAnchor, constant: 3).isActive = true
label.bottomAnchor.constraint(equalTo: newView.bottomAnchor).isActive = true
print(label.frame.size.height)
newView.heightAnchor.constraint(equalToConstant: label.frame.size.height).isActive = true
}
While this works and does scroll, you should really be using a UICollectionView to custom UICollectionViewCell's to handle a scroll like this.
Upvotes: 1
Reputation: 14397
Your trailing constraint is not. correct
label.trailingAnchor.constraint(equalTo: newView.trailingAnchor, constant: 3).isActive = true
its going out of newView ... set it like this to give 3 points padding
label.trailingAnchor.constraint(equalTo: newView.trailingAnchor, constant: -3).isActive = true
Upvotes: 0