swiftswiftuigridlazyvgridlazyhgrid

How to make a lazyvgrid/ lazyhgrid scroll horizontally maintaining its appearance?


I’m trying to create a lazyvgrid which has 1 row and scrolls horizontally but i must be missing something since everything I try messes up my layout.

What i want to achieve:
enter image description here

A grid like this (with just 1 row) that is able to scroll horizontally.

What I am doing:

Now I have two solutions which I am not satisfied with:

var days: [Int] = [1,2,3,4,5,6,7]
[…]

 GeometryReader{ geometry in
 ScrollView(.horizontal){
                LazyVGrid(columns:  [GridItem(.adaptive(minimum: geometry.size.width * 0.12))]) {
                    
                   ForEach(days[0..<days.count], id: \.self) {focus in
                      Circle()
                           .foregroundColor(.yellow)
                           .frame(width: 50, height: 50, alignment: .center)
                   }
           }
       }
}

Which results in the following:
enter image description here


 GeometryReader{ geometry in
     ScrollView(.horizontal){
                LazyHGrid(rows:  [GridItem(.adaptive(minimum: geometry.size.width * 0.12))]) {
                    
                   ForEach(days[0..<days.count], id: \.self) {focus in
                      Circle()
                           .foregroundColor(.yellow)
                           .frame(width: 50, height: 50, alignment: .center)
                   }
           }
        }
}

And it looks like this enter image description here Now here if we change the minimum size to 200 or another big number, i Get 1 row but the collection view remains very tall, instead i only want it to be as tall as the items inside of it are.

for reference, it looks like this:
enter image description here

Can you explain me how to successfully achieve what i need and why this is happening? I really would like to learn more about grids in swiftui, i was very good with collection views in UIKit and it’s frustrating not having the same with grids…


Solution

  • As you set a defined .frame(width: 50, height: 50, alignment: .center) you won't need GeometryReader.

    You can do either this:

            ScrollView(.horizontal){
                LazyHGrid(rows: [ GridItem(.flexible()) ]) {
                    ForEach(days, id: \.self) {focus in
                        Circle()
                            .foregroundColor(.yellow)
                            .frame(width: 50, height: 50, alignment: .center)
                    }
                }
            }
    

    or skip Grid entirely and use LazyHStack, which would be the more natural pick if you only have one row.:

            ScrollView(.horizontal){
                LazyHStack {
                    ForEach(days, id: \.self) {focus in
                        Circle()
                            .foregroundColor(.yellow)
                            .frame(width: 50, height: 50, alignment: .center)
                    }
                }
            }