0
votes

I have to dynamically create some UILabel and UITextViews according to some Data ~ around 20 - all of them with dynamic height/lines of Text for an IOS App in Swift.

Since the screen is not large enough I am adding the Views to a ScrollView, but unfortunately the contentsize property of my ScrollView seems not to receive the proper values.

I'm debugging since a couple of hours and tried different set ups but so far none of them worked out.

The sizing is done in a custom method refreshUI() which gets firstly called in viewDidLoad(). The ViewController simply contains one centred Heading Label and the ScrollView which fills the rest of the space (pinned to Top, Left, Right, Bottom with 8.0). Then I'm trying to populate my Data in that scrollView as follows:

func refreshUI(){
    println("refreshUI()")

    questionnaireTitle.text = site.questionnaireName
    let questionnaire = site.questionnaire

    //removes all SubViews in ScrollView
    clearView(scrollView)
    scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)


    for questionGroup in questionnaire{

        //QUESTIONGROUP HEADING
        let questionGroupHeading = UILabel()
        questionGroupHeading.setTranslatesAutoresizingMaskIntoConstraints(false)
        questionGroupHeading.text = questionGroup.questionsHeading
        questionGroupHeading.sizeToFit()
        scrollView.addSubview(questionGroupHeading)
        viewStack.append(questionGroupHeading)


        //QUESTION
        for question in questionGroup.questions{
            //QUESTION LABEL
            let questionLabel = UILabel()
            questionLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
            questionLabel.text = question.text
            questionLabel.numberOfLines = 0
            questionLabel.lineBreakMode = .ByWordWrapping
            questionLabel.sizeToFit()
            scrollView.addSubview(questionLabel)
            viewStack.append(questionLabel)

            if question.type == "selector"{
                //SELECTOR QUESTION
                println("selector Question")

                for statement in question.statements{
                    //TODO add Statement + Picker
                }
            }
            else if question.type == "standard"{
                //STANDARD QUESTION
                println("standard question")
                let answerLabel = UITextField()
                answerLabel.placeholder = "here goes your answer"
                answerLabel.sizeToFit()
                answerLabel.backgroundColor = UIColor.whiteColor()
                answerLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
                scrollView.addSubview(answerLabel)
                viewStack.append(answerLabel)
            }
        }


    }

    //setUpConstraints

    var counter = 0
    var height:CGFloat = 0.0
    for view in viewStack{
        let rightConst = NSLayoutConstraint(item: view, attribute: .Right, relatedBy: .Equal, toItem: scrollView, attribute: .Right, multiplier: 1.0, constant: 0.0)
        let leftConst = NSLayoutConstraint(item: view, attribute: .Left, relatedBy: .Equal, toItem: scrollView, attribute: .Left, multiplier: 1.0, constant: 0.0)
        let widthConst = NSLayoutConstraint(item: view, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: scrollView.frame.width)
        view.addConstraint(widthConst)
        scrollView.addConstraint(leftConst)
        scrollView.addConstraint(rightConst)

        //pin first view to top of scrollView
        if counter == 0{
            let topConst = NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: scrollView, attribute: .Top, multiplier: 1.0, constant: 0.0)
            scrollView.addConstraint(topConst)
        }
        //pin all other views to the top of the previousView
        else{
            let topConst = NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: viewStack[counter - 1], attribute: .Bottom, multiplier: 1.0, constant: 8.0)
            scrollView.addConstraint(topConst)
        }
        counter++

        height += view.bounds.height
    }


    let contentSize = CGSize(width: scrollView.frame.width, height: height)
    scrollView.contentSize = contentSize
    scrollView.contentOffset = CGPoint(x: 0, y: 0)

    println("refreshUI() done")
}

The ScrollView is not vertically scrollable, although some content is not displayed due to being out of the screen. But it scrolls horizontally, although I'm setting the width of each view to the width of the SCrollView, which should mean that every SubView is just as big as the size of the ScrollView and thus not vertically scrollable.

2

2 Answers

0
votes

If you are using AutoLayout then this tutorial will be useful for implementing scrollview.

0
votes

When you run refreshUI() inside of viewDidLoad(), the subviews that are being created are using the Interface Builder defaults for the parent views instead of the actual sizes on the device. This is likely why your sizes are not what you expect. If you run refreshUI() inside of viewDidLayoutSubviews() instead, then the subviews will correctly read the widths and heights of the parent view.