I have varying amount of data that needs to be displayed as per image below, notice how when there is odd amount of data, grid adopts to stretch respected items to span across 2 columns
So far, my best stab at this was to have a LazyVGrid
like this
LazyVGrid(
columns: [GridItem(.adaptive(minimum: thirdOfScreen, maximum: .infinity))],
spacing: 8
) {
// ...
}
here thirdOfScreen
is essentially what it says, a third of the screen width. This was my attempt to force only 2 items per row (used third and not half to account for various paddings between and around items).
This worked to an extent, however if there are 1 or 3 items, they don’t stretch to full width of the row.
2
Answers
You can use
Grid
andGridRow
to define the layout, and usegridCellColumns
to specify the space each cell will occupy within the grid.In this example, the grid is divided into 4 columns. Each
GridRow
specifies how many of those columns each cell will occupy.Following this, you can implement your logic to know if the last
GridRow
would have one or two cells.It is possible to do this with a
LazyVStack
withHStack
s inside it. You want the items in eachHStack
to fill theHStack
equally.All you need to do is to split the data you want to display into chunks of 2, and use
.frame(maxWidth: .infinity)
on each item so they fill theHStack
equally.Here is an example implementation that uses
chunks(ofCount:)
from Swift Algorithms, andExtract
from View Extractor.You technically don’t need to add any dependencies if you don’t like dependencies. It’s not hard to write a
chunks(ofCount:)
yourself, and View Extractor is small enough that you can easily look at its source code and write something similar yourself.Usage:
The slight downside of this approach is that animations look a bit janky if an item is inserted in/removed from the "grid", except in the last row, where the animation looks fine.