Home > Net >  How to display a fixed amount of items in HStack
How to display a fixed amount of items in HStack

Time:09-09

I want to loop through an array of items and display 3 of them in one HStack for every other item in the array I want to display them in the next line again for 3 items and so on.

It should look something like this: enter image description here

My code so far lets the items appear in the same line:

struct FeedBlockView: View {
    let cardSize = (UIScreen.main.bounds.size.width / 3) - 1
    @State var feedPosts: [FeedPost]

    var body: some View {
        HStack(spacing: 2) {
            ForEach(feedPosts, id: \.id) { feedPost in
                WebImage(url: URL(string: feedPost.feedImageUrl))
                        .resizable()
                        .frame(width: cardSize, height: cardSize)
            }
        }
    }
} 

CodePudding user response:

You have two options:

You can either use a LazyVGrid and have three columns:

import SwiftUI

LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], spacing: 5) {
    ForEach(feedpostArray, id: \.id) { post in
        // yourCOntent
    }
}

Or if you don't want your views to load lazily, you can split your array so your array contains arrays that has three posts each (except the last one if the math doesn't go up):

VStack {
    ForEach(feedposts.chunked(into: 3), id: \.self) { feedpostArray in
        HStack(spacing: 7) {
            ForEach(feedpostArray, id: \.id) { post in
                // yourCOntent

                if feedpostArray.count != 3 {
                     // something to fill the last row it is less than three (Color.clear for example)
                }

            }
        }
    }
}

And the extension for split:

// MARK: - Array to chunks
extension Array {
    func chunked(into size: Int) -> [[Element]] {
        return stride(from: 0, to: count, by: size).map {
            Array(self[$0 ..< Swift.min($0   size, count)])
        }
    }
}
  • Related