1
votes

How should I setup auto layout constrains so that multiline label stays vertically centered inside scrollview until it's text content becomes too long to be shown at once? When the text length becomes too long text should be aligned at top with the scrollview so the user can see the beginning of text and scroll for more. This is how I tried to setup constrains

for scrollView:

  • Equal Height to: Superview
  • Align Trailing to: Safe Area, Equals = -8
  • Align Leading to: Safe Area, Equals = 8
  • Align Top to: Safe Area

for label:

  • Leading Space to: Superview
  • Equal Width to: Superview
  • Align Center Y to: Superview

I also added following code to viewDidLoad()

scrollView.contentLayoutGuide.bottomAnchor.constraint(equalTo: label.bottomAnchor).isActive = true

The problem is that but I still get some warnings and also text ends up "vertically centered" inside scrollview without possibility to really scroll to the beginning or the end of it, even when it can not fit whole inside. For scrollview I get warning that it "has ambiguous scrollable content width", while for the label I get warning "trailing constraint is missing, which may cause overlapping with other views"

1
Just constrain the label to leading, top, trailing, bottom of scrollView. - creeperspeak
Why not use a UITextView? You can set the UITextView to infer its height from its content and it will become scrollable once it reaches a particular size based on your constraints. - Rikh
@creeperspeak constraining all label sides to scrollview doesn't work - Code Poetics
@Rikh Content shouldn't be editable. I know you can disable editing of text view, but it seems there's even more job to make text inside textview centered vertically - Code Poetics

1 Answers

1
votes

How about constraining the label height to the height of the scrollView's superview? In that case the label will be always as big as the screen where it is presented, and since by default the text in a UILabel is centered vertically, you would get what you want. See the following Playgrounds example for reference:

import PlaygroundSupport
import UIKit

class A: UIViewController {
    let scrollView = UIScrollView()
    let label = UILabel()

    override func viewDidLoad() {
        self.view.backgroundColor = .white
        self.view.addSubview(scrollView)
        self.scrollView.addSubview(label)

        label.numberOfLines = 0

        label.text = "How should I setup auto layout constrains so that multiline label stays vertically centered inside scrollview until it's text content becomes too long to be shown at once?"

        scrollView.translatesAutoresizingMaskIntoConstraints = false
        label.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
            scrollView.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor),
            scrollView.rightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.rightAnchor),

            label.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor),
            label.rightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.rightAnchor),
            label.topAnchor.constraint(equalTo: self.scrollView.topAnchor),
            label.bottomAnchor.constraint(equalTo: self.scrollView.bottomAnchor),

            label.heightAnchor.constraint(greaterThanOrEqualTo: self.view.heightAnchor),

            ])
    }
}

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = A()