I have a 4 x 1 UILabel matrix in a horizontal stackview I would like columns 1 and 3 to be the same width BUT narrower than columns 2 and 4. I have tried .fillproportionally, and others. I understood that this was possible... however, a solution evades me and Google hasn't turned anything up. Any help or a point in the right direction would be helpful. Thank you. I am not using Storyboards.
Asked
Active
Viewed 203 times
1
-
How do you want to determine your "column" widths? C1 & C3 should be equal, but based on what? The one with more text? And, narrower than C2 & C4, but again, based on what? Suppose your "column" text is `a | word | longer text | short`? How do you want that to get laid-out? – DonMag Apr 27 '20 at 18:12
-
C1 should be a third of C2 and C3 should be a third of C4. The words in C1 and C3 are annotations as single words. The content in C2 and C4 is calculated values and therefore variable. – user3194306 Apr 28 '20 at 20:07
-
hmmm.. so, `C1 == C2 * 0.333` and `C3 == C4 * 0.333` but C2 may not be equal to C4, so C1 & C3 will be different widths? – DonMag Apr 28 '20 at 21:08
-
Much easier to understand what you're going for if you give us a few examples of the content. – DonMag Apr 28 '20 at 21:10
-
For example, in this image: https://i.stack.imgur.com/AwXuD.png all **C1** labels are 1/3 the width of **C2** (cyan), and all **C3** labels are 1/3 the width of **C4** (green). But, as is obvious, **C1** widths are **not equal** to **C3** widths. – DonMag Apr 28 '20 at 21:34
-
C1 will hold the following HOLDING, BOOK, P/L. C3 will hold the following PAID, MARKET, WEIGHT. I really appreciate your help however I thought that the answer might lie with the contraints and multiples thereof, within the UIStackview – user3194306 Apr 29 '20 at 08:49
-
You *can* do this with stackView / constraints / multipliers / etc (that's what I did in the image I linked), but you still haven't clarified what ***exactly*** you want to do. Suppose `C2-w` is **120** and `C4-w` is **180**. You want `C1-w` to be **1/3 of C2 = 40** and you want `C3-w` tp be **1/3 of C4 = 60** ... ***AND*** you want `C1-w == C3-w`. So, how can you have `40 == 60`? That's why I said show actual examples of your "column content" --- better yet, lay out a couple examples manually and post that image to make it clear. – DonMag Apr 29 '20 at 13:06
-
https://i.stack.imgur.com/uPha8.png – user3194306 Apr 30 '20 at 14:15
-
I would like columns 1 and 3 to be the same width BUT narrower than columns 2 and 4.See visual. – user3194306 Apr 30 '20 at 14:19
2 Answers
0
You can create your grid:
as you described:
C1-w == 1/3 of C2-w
C3-w == C1-w
C4-w == C2-w
pretty much with that description:
with the stack view .distribution = .fill
Here's a complete example:
class ColumnStackViewController: UIViewController {
let outerStack: UIStackView = {
let v = UIStackView()
v.translatesAutoresizingMaskIntoConstraints = false
v.axis = .vertical
v.alignment = .fill
v.distribution = .fill
v.spacing = 8
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
// create "header row" stack view
let headerRowStack = UIStackView()
headerRowStack.axis = .horizontal
headerRowStack.spacing = 4
// create 4 labels for header row
let headerC1 = UILabel()
let headerC2 = UILabel()
let headerC3 = UILabel()
let headerC4 = UILabel()
headerC1.text = "C1"
headerC2.text = "C2"
headerC3.text = "C3"
headerC4.text = "C4"
[headerC1, headerC2, headerC3, headerC4].forEach { v in
// give each "header" label a background color, so we can see the frames
v.backgroundColor = .yellow
v.textAlignment = .center
headerRowStack.addArrangedSubview(v)
}
NSLayoutConstraint.activate([
// constrain c1 width to 1/3 of c2 width
headerC1.widthAnchor.constraint(equalTo: headerC2.widthAnchor, multiplier: 1.0 / 3.0),
// constrain c3 width equal to c1 width
headerC3.widthAnchor.constraint(equalTo: headerC1.widthAnchor),
// constrain c4 width equal to c2 width
headerC4.widthAnchor.constraint(equalTo: headerC2.widthAnchor),
])
outerStack.addArrangedSubview(headerRowStack)
let c1Vals = ["HOLDING", "BOOK", "P/L"]
let c3Vals = ["PAID", "MARKET", "WEIGHT"]
for i in 0..<c1Vals.count {
// create a "row" stack view
let rowStack = UIStackView()
rowStack.axis = .horizontal
rowStack.spacing = headerRowStack.spacing
// add it to outer stack view
outerStack.addArrangedSubview(rowStack)
let rowC1 = UILabel()
let rowC2 = UILabel()
let rowC3 = UILabel()
let rowC4 = UILabel()
rowC1.text = c1Vals[i]
rowC3.text = c3Vals[i]
rowC2.text = "row \(i+1) c2 data"
rowC4.text = "row \(i+1) c4 data"
[rowC1, rowC2, rowC3, rowC4].forEach { v in
// give each row-label a border
v.layer.borderColor = UIColor.red.cgColor
v.layer.borderWidth = 0.5
// set the font
v.font = UIFont.systemFont(ofSize: 14.0, weight: .light)
// add it to the row stack view
rowStack.addArrangedSubview(v)
}
// constrain each row-label width to the header-row label width
for (hLabel, rowLabel) in zip([headerC1, headerC2, headerC3, headerC4], [rowC1, rowC2, rowC3, rowC4]) {
rowLabel.widthAnchor.constraint(equalTo: hLabel.widthAnchor).isActive = true
}
}
view.addSubview(outerStack)
// respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain outer stack view to Top / Leading / Trailing with 20-pt "padding"
outerStack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
outerStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
outerStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
])
}
}
which produces this result:
Note: you'll have to use a pretty small font to fit that layout on a small device:

DonMag
- 69,424
- 5
- 50
- 86
-
1Hi This is all i ended needing v1.widthAnchor.constraint(equalTo: v2.widthAnchor, multiplier: 0.5, constant: 0).isActive = true v3.widthAnchor.constraint(equalTo: v1.widthAnchor ).isActive = true v4.widthAnchor.constraint(equalTo: v2.widthAnchor ).isActive = true – user3194306 May 03 '20 at 13:32
-
@user3194306 /UIStackView observes your layout w/constraints. I had horiz. UIStackView w/3 small images & 1 text label, where SV cell size was calc'd based on image size, & squeezed label (ellipsis). Intrinsic size wasn't set, compression or something. Setting layout constraint width anchor fixed it! UIStackView accommodated, however, changing the width of the the item increased size of image items of the stackView with distribution =fillEqually, .fillProportionally, ... .centerEqually less so. So you may have to play around SV variables to get it right. https://nshipster.com/uistackview/ – clearlight Apr 18 '23 at 00:23
0
This is all i ended needing v1.widthAnchor.constraint(equalTo: v2.widthAnchor, multiplier: 0.5, constant: 0).isActive = true v3.widthAnchor.constraint(equalTo: v1.widthAnchor ).isActive = true v4.widthAnchor.constraint(equalTo: v2.widthAnchor ).isActive = true

user3194306
- 81
- 1
- 7