2

I have a LazyVGrid with 2 columns in my ContentView. I want to add full width item on every n'th index of the grid. In this code snippet I am trying to add full width item only in the 2nd position for testing. How can I achieve this ? Thanks in advance

`LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], alignment: .center) {
    ForEach(0..<10, id: \.self) { index in
        if index == 2 {
            Text("Full Width Item")
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 100)
                .background(Color.gray)
                .foregroundColor(.white)
                .cornerRadius(8)
                .padding()
        } else {
            Text("Regular Item")
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 50)
                .background(Color.green)
                .foregroundColor(.white)
                .cornerRadius(8)
                .padding()
        }
    }
}`

I am tring to achieve something like this.

Akhil
  • 93
  • 7

1 Answers1

2

Here's a solution using a GeometryReader to get the width of the LazyVGrid to calculate the cell sizes.

The regular cells are the same as in your sample code, but for the full width cell, I'm using a Color.clear and overlaying it with the large cell, and then using another Color.clear to fill space for the second cell in the row.

struct ContentView: View {
        
    let spacing: CGFloat = 20
    let columnCount = 2
    
    var columns: [GridItem] {
        Array(repeatElement(GridItem(.flexible()), count: columnCount))
    }
    
    var body: some View {
        GeometryReader { proxy in
            LazyVGrid(columns: columns, alignment: .center) {
                ForEach(0..<10, id: \.self) { index in
                    if index == 2 {
                        Color.clear
                            .frame(minHeight: 100)
                            .overlay(alignment: .leading) {
                                Text("Full Width Item \(index)")
                                    .frame(maxHeight: .infinity)
                                    .frame(width: proxy.size.width)
                                    .background(Color.gray)
                                    .foregroundColor(.white)
                                    .cornerRadius(8)

                            }
                        Color.clear
                    } else {
                        Text("Regular Item \(index)")
                            .frame(width: cellWidth(for: proxy.size))
                            .frame(minHeight: 100)
                            .background(Color.green)
                            .foregroundColor(.white)
                            .cornerRadius(8)
                            .padding()
                    }
                }
            }
        }
        .padding()
    }
    
    func cellWidth(for size: CGSize) -> CGFloat {
        (size.width - ((CGFloat(columnCount) - 1) * spacing)) / CGFloat(columnCount)
    }
}

enter image description here

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
  • Thanks for your quick response. overlay(alignment: .leading) is only available from iOS 15, but my app has deployment target iOS 14. – Akhil Jan 26 '23 at 21:26
  • Ashley Mills , I am actually using this LazyVGrid inside a VStack (because I have other items above the LazyVGrid) which is embedded in a Scrollview. if I add GeometryReader inside a Scrollview, it won't scroll properly.. – Akhil Jan 26 '23 at 21:31
  • Scrolling works fine if you put the `ScrollView` inside the `GeometryReader`, although that doesn't help with the iOS 14 problem. – Ashley Mills Jan 26 '23 at 22:00
  • In the screenshot you added, How to add a full-width Item in the 10 position? which is in the next line. – Akhil Jan 28 '23 at 12:14