Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIStackView and truncated Multiline UILabels

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

like image 543
Flori Avatar asked Nov 02 '15 12:11

Flori


2 Answers

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)
    })
}
like image 116
Ajil O. Avatar answered Oct 19 '22 07:10

Ajil O.


As per I know If you are using this inside UITableViewCell then each rotation you have to reload tableView. You can use stackView.distribution = .fillProportionally it will work fine.

like image 31
Sagar Daundkar Avatar answered Oct 19 '22 07:10

Sagar Daundkar