0

While I put a single UILabel into the stack of UIStackView, everything works fine as expected. But what I need is to actually put a UIView under the UILabel and keep the self-size of UILabel to be kept. I just wondering, is there is a way to achieve this without using UITableView and self-sized cell? I used this code

let textLabel = UILabel()
    textLabel.text = "zaciatok TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT koniec"
    textLabel.numberOfLines = 0
    textLabel.sizeToFit()
    textLabel.backgroundColor = .yellow
    let testItemView = UIView()
    testItemView.backgroundColor = .green
    testItemView.addSubview(textLabel)
    mainStackView.addArrangedSubview(testItemView)

but it shows the text with only one line which is not making the thing I need.

I have tried the new suggestion with the code

mainStackView.distribution = .fill
    let textLabel = UILabel()
    textLabel.text = "zaciatok TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT koniec"
    textLabel.numberOfLines = 0
    textLabel.sizeToFit()
    textLabel.backgroundColor = .yellow
    let testItemView = UIView()

    testItemView.backgroundColor = .green
    testItemView.addSubview(textLabel)

    mainStackView.addArrangedSubview(testItemView)
    testItemView.translatesAutoresizingMaskIntoConstraints = false
    testItemView.heightAnchor.constraint(equalToConstant: 50).isActive = true

I get

enter image description here

when I remove sizeToFit, there is no label at all My constraints of stackview:enter image description here

RajeshKumar R
  • 15,445
  • 2
  • 38
  • 70
Vanya
  • 4,973
  • 5
  • 32
  • 57
  • Do you want to add padding to the label from the testItemView? – RajeshKumar R May 16 '19 at 17:22
  • @RajeshKumarR Yes but, the padding is asymmetric with 3 rounded corners a one without rounded corner, so I believe I need a UIView under the UILabel to achieve this. – Vanya May 16 '19 at 17:26

2 Answers2

2

Try this

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .white

        let mainStackView = UIStackView()
        mainStackView.axis = .vertical
        mainStackView.spacing = 3
        mainStackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(mainStackView)

        mainStackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(10)-[mainStackView]-(10)-|", options: [], metrics: nil, views: ["mainStackView":mainStackView]))

        let testItemView = UIView()
        testItemView.layer.maskedCorners = [.layerMinXMinYCorner,.layerMinXMaxYCorner,.layerMaxXMinYCorner]
        testItemView.layer.cornerRadius = 15.0
        testItemView.layer.masksToBounds = true
        testItemView.backgroundColor = .green
        testItemView.translatesAutoresizingMaskIntoConstraints = false

        let textLabel = UILabel()
        textLabel.translatesAutoresizingMaskIntoConstraints = false
        textLabel.text = "zaciatok TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT TEXT TEXTTEXT TEXT koniec"
        textLabel.numberOfLines = 0
        textLabel.lineBreakMode = .byWordWrapping
        textLabel.backgroundColor = .yellow
        testItemView.addSubview(textLabel)

        testItemView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(5)-[textLabel(>=30)]-(5)-|", options: [], metrics: nil, views: ["textLabel":textLabel]))
        testItemView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(5)-[textLabel]-(5)-|", options: [], metrics: nil, views: ["textLabel":textLabel]))

        mainStackView.addArrangedSubview(testItemView)
    }
}

enter image description here

RajeshKumar R
  • 15,445
  • 2
  • 38
  • 70
  • adding constraints to elements inside a stackview isn't correct for items with intrinsic content size , there is no meaning for a stackview here as yo deal with it as if it's a usaual `UIView` – Shehata Gamal May 16 '19 at 17:50
  • @Sh_Khan Without constraints we cant add padding to greenview to yellow label – RajeshKumar R May 16 '19 at 17:50
  • there is a `spacing` proeprty – Shehata Gamal May 16 '19 at 17:51
  • @Sh_Khan spacing property of stackview is used between arranged subviews. In a chat application that spacing will be between one chat to another chat. Here constraints are used to give space between green super view to yellow subview label – RajeshKumar R May 16 '19 at 17:53
  • @Sh_Khan Check [this](https://i.stack.imgur.com/cOsv0.png) spacing value 20 is used between both green views. Constraint space 5 is used between green view and it's subview yellow label – RajeshKumar R May 16 '19 at 17:57
  • @Sh_Khan Using tableview is best for this design. But OP mentioned _"without using UITableView and self-sized cell"_ – RajeshKumar R May 16 '19 at 18:05
  • @Vanya Have you added this stackview in a scrollview? – RajeshKumar R May 16 '19 at 18:07
  • @RajeshKumarR actually it is in a scrollView, haven't tried yet, but I expect it is gonna work well, any specific reason? – Vanya May 16 '19 at 18:51
  • @Vanya Why don't you use tableview? – RajeshKumar R May 16 '19 at 18:53
  • @RajeshKumarR there are basically two views in the scrollView, one is sort of chat, but it is not only text, mostly it is another views with dynamic size, and when user decide, any item with this more complex views have to be visible in the another view, so I believe that UIstackView is better for this kind behaviour, what do you think? – Vanya May 16 '19 at 18:56
  • @Vanya I guess you can use 2 prototype cells. One for simple text and another one for another view – RajeshKumar R May 16 '19 at 18:58
  • 1
    @RajeshKumarR the problem is more complex, there are about 10 different views with charts, sort of tables , text, so on, OK I can make so many cells, but I need to remove it from first then add to the second in a certain order that is up to the user, so when it become this complex I think StackView is better – Vanya May 16 '19 at 19:03
  • @RajeshKumarR your solution works only for normal text. Do you know how to fix this with attributed text: https://stackoverflow.com/questions/61810097/how-to-remove-bottom-padding-of-uilabel-with-attributedtext-inside-uistackview – Matthias May 15 '20 at 01:19
0

1- For the text inside the label to wrap , mainStackView must be hooked properly with leading & trailing constraints ( sure also with top & bottom for automatic sizing )

2- You need to remove

textLabel.sizeToFit()

3- The view you add has no intrinsic content size like the label , so you need to give it a static height constraint

let testItemView = UIView()
testItemView.translatesAutoresizingMaskIntoConstraints = false
testItemView.heightAnchor.constraint(equalToConstant: 50).isActive = true

4- Set

mainStackView.distribution = .fill
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87