I have one UIStackView that stacks vertically two horizontal UIStackViews. That worked just fine. But the first sub-UIStackView had too many elements so I decided to wrap it inside a scrollView. The problem is that when I do so, this first sub-view just disappears, as if the UIScrollView had a height of 0.
Here’s the code:
func initViews(){
let containerStack = UIStackView()
addSubview(containerStack)
containerStack.axis = .vertical
containerStack.distribution = .equalCentering
containerStack.isLayoutMarginsRelativeArrangement = true
containerStack.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
let scrollView = UIScrollView()
let scrolledStack = UIStackView()
containerStack.addArrangedSubview(scrollView)
scrollView.addSubview(scrolledStack)
scrolledStack.distribution = .fill
scrolledStack.isLayoutMarginsRelativeArrangement = true
scrolledStack.layoutMargins = UIEdgeInsets(top: 20, left: 30, bottom: 20, right: 30)
scrolledStack.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
scrolledStack.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
scrolledStack.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
scrolledStack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
scrolledStack.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
let otherStack = UIStackView()
containerStack.addArrangedSubview(otherStack)
otherStack.distribution = .equalCentering
otherStack.isLayoutMarginsRelativeArrangement = true
otherStack.layoutMargins = UIEdgeInsets(top: 20, left: 30, bottom: 0, right: 30)
containerStack.translatesAutoresizingMaskIntoConstraints = false
containerStack.topAnchor.constraint(equalTo: topAnchor).isActive = true
containerStack.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
containerStack.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
containerStack.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
for number in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]{
let text = UITextView()
text.font = UIFont.boldSystemFont(ofSize: 14)
text.text = number
text.isScrollEnabled = false
text.backgroundColor = .clear
scrolledStack.addArrangedSubview(text)
}
for number in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]{
let text = UITextView()
text.font = UIFont.boldSystemFont(ofSize: 14)
text.text = number
text.isScrollEnabled = false
text.backgroundColor = .clear
otherStack.addArrangedSubview(text)
}
}
otherStack behaves as expected, but scrollView and scrolledStack just don’t appear. If I remove the scrollView and just add scrolledStack to containerStack, both stacks appear as expected.
2
Answers
Many UI view elements – such as
UIScrollView
– have no intrinsic height.You are putting a scroll view in a vertical stack view, with your stack view set to:
The problem comes in because the stack view cannot center its arranged subviews if they have no height.
If you change your
containerStack
to:You will see both of the arranged subviews.
If you don’t want them to have equal heights, then you need to provide some height value… either with an explicit
scrollView.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
or perhaps relative to the overall height.Edit – in response to comment…
Add these lines at the bottom of your
initViews()
func:and, instead of
.clear
, give your first set of text views:and your second set of text views:
Here’s how it looks now when I run your code:
That is probably not what you’re going for, but by giving your views contrasting background colors, it makes it much easier to see what’s going on.
I readapted a bit your code and created this swift playground: