I'm having some problem resizing and making scrollview scrollable vertically when content is added to my labels. My hierarchy looks like this:
While my view looks like this:
So I would like to fill out labels with content in my code on start when I get text from API call. But for testing purposes I have just hardcoded some lorem ipsum text to make it work. So my content is added to labels and UILabels resize and also my views that containt labels resize. I'm having problem resizing my scrollview content so that I can scroll if text in label is longer. Also here is my current code:
import UIKit
import PureLayout
class QuestionAndAnswerViewController: UIViewController {
@IBOutlet var menuButton: UIBarButtonItem!
@IBOutlet var questionView: UIView!
@IBOutlet var questionLabel: UILabel!
@IBOutlet var questionContentLabel: UILabel!
@IBOutlet var answerView: UIView!
@IBOutlet var odgovorLabel: UILabel!
@IBOutlet var answerLabel: UILabel!
@IBOutlet var signLabel: UILabel!
@IBOutlet var lineView: UIView!
@IBOutlet var scrollView: UIScrollView!
@IBOutlet var contentView: UIView!
var yPosition: CGFloat = 0.0
var contentSize: CGFloat = 0.0
var attrText = NSMutableAttributedString()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.setNeedsLayout()
scrollView.layoutIfNeeded()
scrollView.translatesAutoresizingMaskIntoConstraints = false
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5
paragraphStyle.alignment = .justified
let paragraphStyle2 = NSMutableParagraphStyle()
paragraphStyle2.lineSpacing = 5
paragraphStyle2.alignment = .left
if self.revealViewController() != nil {
self.revealViewController().frontViewShadowRadius = 5.0
self.revealViewController().frontViewShadowOpacity = 0.25
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.rightRevealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
var text = "To je prvo vprašanje? Kako dolgi je lahko ta tekst da se poravna"
attrText = NSMutableAttributedString(string: text)
attrText.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle2, range: NSMakeRange(0, attrText.length))
questionLabel.attributedText = attrText
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut quis mi nisi. Etiam nec augue id dui blandit ornare. Nulla auctor, purus vel tincidunt ultricies, enim turpis molestie augue, nec mattis libero ante mattis mauris. Suspendisse posuere, velit posuere viverra feugiat, nulla justo bibendum nisi, nec ultricies lorem enim in nisl. Nunc sit amet quam mollis, faucibus felis eu, posuere dui. Sed vel mattis neque. Fusce elementum at nisl ut volutpat. Nam placerat consequat mi in lacinia. Morbi ut est tristique, efficitur est a, faucibus erat. Suspendisse et ligula ac lacus porttitor pretium ut vehicula felis."
attrText = NSMutableAttributedString(string: text)
attrText.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, attrText.length))
questionContentLabel.attributedText = attrText
text = "Cras auctor ullamcorper ullamcorper. Vestibulum dignissim quis risus eget congue. Sed et diam libero. Phasellus non lectus sem. Cras auctor ullamcorper ullamcorper. Vestibulum dignissim quis risus eget congue. Sed et diam libero. Phasellus non lectus sem. Cras auctor ullamcorper ullamcorper. Vestibulum dignissim quis risus eget congue. Sed et diam libero. Phasellus non lectus sem. Cras auctor ullamcorper ullamcorper. Vestibulum dignissim quis risus eget congue. Sed et diam libero. Phasellus non lectus sem."
attrText = NSMutableAttributedString(string: text)
attrText.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, attrText.length))
answerLabel.attributedText = attrText
setupConstraints()
contentView.frame = CGRect(x: contentView.frame.origin.x, y: contentView.frame.origin.y, width: contentView.frame.width, height: 2000)
scrollView.contentSize = CGSize(width: contentView.frame.width, height: 2000)
print(scrollView.contentSize)
}
func setupConstraints() {
//Question Contstraints
questionView.autoPinEdge(.top, to: .top, of: contentView, withOffset: 30)
questionView.autoPinEdge(.left, to: .left, of: contentView, withOffset: 0)
questionView.autoPinEdge(.right, to: .right, of: contentView, withOffset: 0)
questionView.autoPinEdge(.top, to: .top, of: questionLabel, withOffset: -10)
questionLabel.autoPinEdge(.right, to: .right, of: questionView, withOffset: -20)
questionLabel.autoPinEdge(.left, to: .left, of: questionView, withOffset: 20)
lineView.autoPinEdge(.top, to: .bottom, of: questionLabel, withOffset: 20)
lineView.autoPinEdge(.left, to: .left, of: questionView, withOffset: 20)
lineView.autoPinEdge(.right, to: .right, of: questionView, withOffset: -20)
lineView.autoSetDimensions(to: CGSize(width: lineView.frame.width, height: 2))
questionContentLabel.autoPinEdge(.top, to: .bottom, of: lineView, withOffset: 20)
questionContentLabel.autoPinEdge(.right, to: .right, of: questionView, withOffset: -20)
questionContentLabel.autoPinEdge(.left, to: .left, of: questionView, withOffset: 20)
questionView.autoPinEdge(.bottom, to: .bottom, of: questionContentLabel, withOffset: 20)
//Anwser Constraints
answerView.autoPinEdge(.top, to: .bottom, of: questionView, withOffset: 10)
answerView.autoPinEdge(.left, to: .left, of: contentView, withOffset: 0)
answerView.autoPinEdge(.right, to: .right, of: contentView, withOffset: 0)
odgovorLabel.autoPinEdge(.top, to: .top, of: answerView, withOffset: 10)
odgovorLabel.autoPinEdge(.left, to: .left, of: answerView, withOffset: 20)
odgovorLabel.autoPinEdge(.right, to: .right, of: answerView, withOffset: -20)
answerLabel.autoPinEdge(.top, to: .bottom, of: odgovorLabel, withOffset: 20)
answerLabel.autoPinEdge(.left, to: .left, of: answerView, withOffset: 20)
answerLabel.autoPinEdge(.right, to: .right, of: answerView, withOffset: -20)
signLabel.autoPinEdge(.top, to: .bottom, of: answerLabel, withOffset: 20)
signLabel.autoPinEdge(.left, to: .left, of: answerView, withOffset: 20)
signLabel.autoPinEdge(.right, to: .right, of: answerView, withOffset: -20)
contentView.autoPinEdge(.bottom, to: .bottom, of: answerView)
//answerView.autoPinEdge(.bottom, to: .bottom, of: signLabel, withOffset: 20)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func backButtonPressed(_ sender: Any) {
navigationController?.popViewController(animated: true)
}
}
I'm also using PureLayout because it was the only way I was able to make my labels and view resize based on text length.
I'm not sure what constraints do you set for
scrollView
andcontentView
in the storyboard, and I must say that I'm a bit curious about why use set frames directly for them inviewDidLayout
:You would like this to be calculated automatically, right?
What I do when I need a scrollable view:
I add a
scrollView
to the hierarchy and use autolayout to properly layout it, e.g., if it is supposed to cover the wholeview
of theviewController
:Then I need to add a
contentView
to thescrollView
and provide a proper layout constraints for it, so if I want vertically scrollablescrollView
in the example I started above, I need following autolayout constraints:Notice here that I constrained the
leftAnchor
andrightAnchor
of thecontentView
to theself.view
rather than toscrollView
to make it of fixed width. However, top and bottom anchors are constrained to the scrollView, so they are expanded and scrollable whencontentView
needs more space.Now I add to the
contentView
all the content that I want, and I lay it out using autolayout as if thecontentView
was a view with infinite height -scrollView
will take care of presenting it whole by scrolling. So in my example if the only content would be one hugeUILabel
with many lines:Try to go over your code and check your constraints (I wrote my constraints using Autolayout, but I guess you should be able to translate them pretty easily both to PureLayout and storyboards).