UIStackView and truncated Multiline UILabels

Flori picture Flori · Nov 2, 2015 · Viewed 8.4k times · Source

I want to add several multiline Labels to an UIStackView.

But I always end up my Labels being truncated. As seen in this Screenshot truncated as it is

But I like to have it more as shown here (my faked Screenshot) truncated as it should be

Here is my Code. First I create the parent/master StackView, put it into an ScrollView (which is tucked to the screen)

    stackView = UIStackView()
    stackView.axis = .Vertical
    stackView.distribution = .Fill
    stackView.spacing = 2
    stackView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(stackView)
    NSLayoutConstraint.activateConstraints(stackConstraints)


    let s1 = createHeaderStackView()
    stackView.insertArrangedSubview(s1, atIndex: 0)

    let lbl2 = makeLabel()
    lbl2.text = "Second One"
    stackView.insertArrangedSubview(lbl2, atIndex: 1)

    scrollView.setNeedsLayout()

while makeLabel and makeButton are just helper functions

func makeButton() -> UIButton {
    let btn = UIButton(type: .Custom)
    btn.backgroundColor = UIColor.lightGrayColor()
    return btn
}

func makeLabel() -> UILabel {
    let lbl = UILabel()
    lbl.font = UIFont.systemFontOfSize(18)
    lbl.setContentCompressionResistancePriority(1000, forAxis: .Vertical)
    lbl.setContentHuggingPriority(10, forAxis: .Vertical)
    lbl.preferredMaxLayoutWidth = scrollView.frame.width
    lbl.numberOfLines = 0
    lbl.textColor = UIColor.blackColor()
    lbl.backgroundColor = UIColor.redColor()
    return lbl
}

The createHeaderStackViewmethod is to configure my StackView to put inside a StackView with all my header stuff.

func createHeaderStackView() -> UIStackView {
    let lblHeader = makeLabel()
    lblHeader.text = "UIStackView"
    lblHeader.textAlignment = .Center

    let lblInfo = makeLabel()
    lblInfo.text = "This is a long text, over several Lines. Because why not and am able to to so, unfortunaltey Stackview thinks I'm not allowed."
    lblInfo.textAlignment = .Natural
    lblInfo.layoutIfNeeded()

    let lblInfo2 = makeLabel()
    lblInfo2.text = "This is a seconds long text, over several Lines. Because why not and am able to to so, unfortunaltey Stackview thinks I'm not allowed."
    lblInfo2.textAlignment = .Natural
    lblInfo2.layoutIfNeeded()

    let btnPortal = makeButton()
    btnPortal.setTitle("My Button", forState: .Normal)
    btnPortal.addTarget(self, action: "gotoPushWebPortalAction", forControlEvents: .TouchUpInside)

    let headerStackView = UIStackView(arrangedSubviews: [lblHeader, btnPortal, lblInfo, lblInfo2])
    headerStackView.axis = .Vertical
    headerStackView.alignment = .Center
    headerStackView.distribution = .Fill
    headerStackView.spacing = 2
    headerStackView.setContentCompressionResistancePriority(1000, forAxis: .Vertical)
    headerStackView.setContentHuggingPriority(10, forAxis: .Vertical)
    headerStackView.setNeedsUpdateConstraints()
    headerStackView.setNeedsLayout()
    //headerStackView.layoutMarginsRelativeArrangement = true
    return headerStackView
}

so to make a long story short: What is needed to adjust my stackviews, so each stackview and therefore label is shown in full glorious size? I tried to compress and hug everything, but it didn't seem to work. And googling uistackview uilabel multiline truncated seems to be a dead end, too

I appreciate any help, regards Flori

Answer

Ajil O. picture Ajil O. · Nov 2, 2016

You have to specify the dimensions of the stack view. The label will not "overflow" into the next line if the dimensions of the stack view is ambiguous.

This code is not exactly the output you'd want, but you'll get the idea:

override func viewDidLoad() {
    super.viewDidLoad()
    let stackView = UIStackView()
    stackView.axis = .Vertical
    stackView.distribution = .Fill
    stackView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(stackView)
    let views = ["stackView" : stackView]
    let h = NSLayoutConstraint.constraintsWithVisualFormat("H:|-50-[stackView]-50-|", options: [], metrics: nil, views: views)
    let w = NSLayoutConstraint.constraintsWithVisualFormat("V:|-100-[stackView]-50-|", options: [], metrics: nil, views: views)
    view.addConstraints(h)
    view.addConstraints(w)
    let lbl = UILabel()
    lbl.preferredMaxLayoutWidth = stackView.frame.width
    lbl.numberOfLines = 0
    lbl.text = "asddf  jk;v ijdor vlb otid jkd;io dfbi djior dijt ioure f i;or dfuu;nfg ior mf;drt asddf  jk;v ijdor vlb otid jkd;io dfbi djior dijt ioure f infg ior mf;drt asddf  jk;v ijdor vlb otid jkd;io dfbi djior dijt ioure f i;or dfuu;nfg ior mf;drt "
    dispatch_async(dispatch_get_main_queue(), {
        stackView.insertArrangedSubview(lbl, atIndex: 0)
    })
}