I'm relatively new to Swift and have a grid layout question: I'm currently using a LazyHGrid with adaptive grid items and a single column to flexibly layout items without a predetermined column count. I determine the number of columns shown by setting a maxWidth the grid layout with a maxWidth based on the number of items to be displayed
What I'm trying to accomplish in each of the scenarios below (with a solution that would scale up too) is essentially to adjust the positions in the examples below by shifting items out of position "" and into position "⚪️", eliminating the "floating orphan" item not hugging the edge. The "⚫️" positions are already correct.
CONSTRAINTS
- I want to minimize the width that this grid uses, but not all rows can accommodate the taller stacks (so setting a bunch of brittle rules seems like a poor solution) and I'm not interested in setting a fixed row item height to remove the need for a dynamic solution
- I'd like to avoid creating grid manually with nested HStacks and VStacks and writing a bunch of extra logic to manage the contents of each row and column given the height of the parent row (as retrieved via GeometryReader).
WHAT I'VE TRIED
- I looked in the Lazy_Grid docs to see if there was a view modifier that would accomplish this -- didn't come across one (though it's entirely possible I've missed it!)
- I thought maybe flipping the layoutDirection (from LTR to RTL) might do it, but no such luck
- I shifted around the alignment values of the repeated gridItem and lazyHGrid container, but the floating orphan remained
EXAMPLES
- For three items:
/* short */
___________
⚫️⚫️|
⚪️|
/* tall */
___________
⚫️|
⚫️|
⚫️|
- For four items:
/* short */
___________
⚫️⚫️|
⚫️⚫️|
/* tall */
___________ ___________
⚫️⚫️| ⚫️⚫️| // NOTE: I *could* constrain the height in this case
⚪️| ⚫️⚫️| // to achieve the 2x2 grid but would rather not
⚪️|
- For five items:
/* short */
___________
⚫️⚫️⚫️|
⚫️⚪️|
/* tall */
___________
⚫️⚫️|
⚫️⚫️|
⚪️|
- For six items:
/* short */
___________
⚫️⚫️⚫️|
⚫️⚫️⚫️|
/* tall */
___________
⚫️⚫️|
⚫️⚫️|
⚫️⚫️|
- For seven items:
/* short */
___________
⚫️⚫️⚫️⚫️|
⚫️⚫️⚪️|
/* tall */
___________
⚫️⚫️|
⚫️⚫️|
⚫️⚫️|
⚪️|
let items = filterItems()
let iconCount = CGFloat(items.count)
let iconSize: CGFloat = 18
let spacing: CGFloat = 2
// NOTE: `iconCount / 2` because the min-height of the parent
// only fits two items. The current item count is 7 and it's
// unlikely that it'd ever do more than double.
let cols = CGFloat(iconCount / 2).rounded(.up)
let maxWidth = calcWidth(for: cols, iconSize: iconSize, spacing: spacing)
let minWidth = cols < 2 ? maxWidth : calcWidth(for: cols - 1, iconSize: iconSize, spacing: spacing)
LazyHGrid(
rows: Array(
repeating: GridItem(
.adaptive(minimum: iconSize, maximum: iconSize),
spacing: spacing,
alignment: .center
),
count: 1
),
alignment: .center,
spacing: spacing
) {
ForEach(0..<items.count, id: \.self) { n in
...item views...
}
}
.frame(minWidth: minWidth, maxWidth: maxWidth)
My brain is stuck on finding a Swift concept similar to CSS's FlexBox justify-content: flex-end; align-items: flex-start but it feels to me there should be a more Flexy/Swifty solution for this that I'm just missing?
(The grid is nested within an HStack currently, and shoved to the top-trailing corner of it's parent with a spacer, effectively accomplishing the align-items: flex-start portion of the Flexbox solution mentioned above asd as shown in the illustrations above)

