'How could I use a SwiftUI LazyVGrid to create a staggered grid?

I'm trying to implement a view that contains a LazyVGrid of staggered images in a grid- as seen in the below Pinterest feed:

enter image description here

I am aware of the WaterfallGird library but I was wondering if there would be a way to implement this functionality with a LazyGrid, instead of an ordinary V/HGrid.



Solution 1:[1]

Beau Nouvelle solution is working, however, it's buggy and glitchy at least of me. Instead of using LazyVGrid if we use HStack with alignment: .top It works better.

Here is the view

var body: some View {

        HStack(alignment: .top) {            
            LazyVStack(spacing: 8) {
                ForEach(splitArray[0]) {...}
            }
            
            LazyVStack(spacing: 8) {
                ForEach(splitArray[1]) {...}
            }
        }
    }

Here is the code to split the array

    private var splitArray: [[Photo]] {
        var result: [[Photo]] = []
        
        var list1: [Photo] = []
        var list2: [Photo] = []
        
        photos.forEach { photo in
            let index = photos.firstIndex {$0.id == photo.id }
            
            if let index = index {
                if index % 2 == 0  {
                    list1.append(photo)
                } else {
                    list2.append(photo)
                }
            }
        }
        result.append(list1)
        result.append(list2)
        return result
        
    }

I know this is not performance but so far only working solution I found.

Here is the full source code

enter image description here

Solution 2:[2]

  1. Split your array into the number of columns you need.
  2. Inside your LazyVGrid create 2 VStacks.
  3. Drop a ForEach in both VStacks and use each of your arrays you created earlier to fill them out.
  4. That’s it

A rough example as follows...

// split array
let splitArrays = ([TileItem], [TileItem])

ScrollView {
    LazyVGrid(*setup GridItems here*) {
        VStack {
            ForEach(splitArrays.0) { tile in
                Image(tile.image)
            }
        }
        VStack {
            ForEach(splitArrays.0) { tile in
                Image(tile.image)
            }
        }
    }
}

It's likely that this isn't very performant, but it should be able to do what you're after.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2