Search code examples
swiftswiftuiios13

How to make the row fill the screen width with some padding using SwiftUI?


I am trying to create a list with cards or rows which grows downwards. It's added to a horizontal scroll view which can have multiple lists.

snap

How to make the card fill the width - some padding of the screen?

The current code is

struct RowView: View {
    var body: some View {
        Rectangle()
        .foregroundColor(.blue)
        .frame(width: 80, height: 80, alignment: .center)  // shows a square, but how to set size depending on screen?
        //.frame(minWidth: 100, maxWidth: .infinity, minHeight: 100, maxHeight: .infinity, alignment: .topLeading)  // nothing shows up
    }
}

struct ListView: View {
    var body: some View {
        ScrollView(.vertical) {
            VStack(spacing: 16) {
                RowView()
                RowView()
                RowView()
            }
            .padding()
        }
    }
}

struct ContentView: View {

    var body: some View {
        ScrollView(.horizontal) {
            HStack {
                ListView()
                ListView()
                ListView()
            }
        }
    }
}

I tried using GeometryReader, but it's not working.


Solution

  • I tried using GeometryReader, but it's not working.

    It's important in which View component you tried GeometryReader.

    • If you are inside a typical View that spans up to the screen's size, you get the width & height of the screen itself.

    • If you are inside a ScrollView environment, you get

      • height of the container in case of .horizontal alignment
      • width of the container in case of .vertical alignment

    I can't actually visualize what you are trying to achieve with both .horizontal & .vertical aligned scroll views. But what you said about the Card like view to be spanned all the way up to the screen width, you can achieve it by using below code: (see the inline comments for better understanding)

    struct RowView: View {
        var body: some View {
            Rectangle()
                .foregroundColor(.blue)
                .frame(height: 150)
                .cornerRadius(10)
        }
    }
    
    struct ListView: View {
        var body: some View {
            // you won't get the width of the container if you embed this view inside a horizontal scroll view which is the case for you
            // so you have to impose the explicit width from the parent view
            ScrollView(.vertical) {
                VStack(spacing: 16) {
                    RowView()
                    RowView()
                    RowView()
                }
                .padding()
            }
        }
    }
    
    struct ContentView: View {
        var body: some View {
            GeometryReader { geometry in
                ScrollView(.horizontal) {
                    HStack {
                        // you have to be explicit about the width of each content of the scroll view as it can't determine width of each content by itself
                        ListView().frame(width: geometry.size.width)
                        ListView().frame(width: geometry.size.width)
                        ListView().frame(width: geometry.size.width)
                    }
                }
            }
        }
    }