LazyVGrid ignores the leading padding of the first element

50 Views Asked by At
struct HomeView: View {
    @ObservedObject var viewModel = CarViewModel()
    let columns = Array(repeating: GridItem(.flexible(), spacing: 20, alignment: .center), count: 2)

var body: some View {
    GeometryReader { geometry in
        VStack{
            Text("Test")
            ScrollView {
                LazyVGrid(columns: columns, spacing: 20) {
                        ForEach(viewModel.cars) { car in
                            CarCard(car: car) {
                                viewModel.addToCart(car: car)
                            }
                        }
                    }
                .padding(20)
            }
        }
    }
}

struct CarCard: View {
let car: Car
let action: () -> Void
@StateObject private var imageLoader = ImageLoader()

var body: some View {
    VStack(alignment: .leading) {
        if let uiImage = imageLoader.image {
            Image(uiImage: uiImage)
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(maxWidth: .infinity, maxHeight: 200)
        } else {
            ProgressView()
        }
        Text("\(car.price ?? "")₺")
            .font(.headline)
            .padding(.vertical, 4).foregroundStyle(.accent)
        
        Text(car.name ?? "")
            .font(.subheadline)
        
        Text(car.model ?? "")
            .font(.subheadline)
        
        Spacer()
        
        Button(action: action) {
            Text("Add to Cart")
                .frame(maxWidth: .infinity)
                .foregroundColor(.white)
                .padding()
                .background(Color.accentColor)
                .cornerRadius(5)
        }
    }.onAppear{
        if let image = car.image {
            imageLoader.loadImage(from: image)
        }
    }
    .padding()
    .background(Color.white)
    .cornerRadius(10)
    .shadow(radius: 5)
}

Image

I've tried many variants but the size of the first element always gets messed up. How can I fix the first element appearing like this? I also added the code of the card component that I developed as a custom, but somehow when I use padding, only the size and padding of the first element is distorted.

2

There are 2 best solutions below

0
Tayfun Sağdıç On BEST ANSWER
Image(uiImage: uiImage)
                        .resizable()
                        .frame(width: (geometry.size.width - 32), height: (geometry.size.height * 0.50 - 32))

I found the problem by adjusting the size of the components inside the card using geometry and making them responsive. As the size of the elements in the card increases, they can become corrupted in the Grid.

enter image description here

1
Alex On

Unable to reproduce your problem. Kindly suggest you next time use a Minimal, Reproducible Example instead of referring to data (pictures) that others don't have.

In any case, your generic code seems to be correct as the below code produces consistent padding. Please try it. I suppose your picture sizes have something to do with it?

struct ContentView: View {
    
    let columns = Array(repeating: GridItem(.flexible(), spacing: 20, alignment: .center), count: 2)
    
    var body: some View {
        GeometryReader { geometry in
            VStack{
                Text("Test")
                ScrollView {
                    LazyVGrid(columns: columns, spacing: 20) {
                        ForEach(1...5, id:\.self) { number in
                            Text("\(number)")
                        }
                    }
                    .padding(20)
                }
            }
        }
    }