I have a grid which fits its column width and row height depending on the available size and a stepper accessed through a settings view on a pop over sheet. In this particular example I have a 13 by 18 grid in portrait orientation and want to implement an 18 by 13 grid when in landscape orientation. Otherwise I get also a 13 by 18 grid with lots of empty space on the sides.
I thought of using a ViewBuilder and an if - else statement to create a Grid with items sorted with 13 columns and 18 rows or 18 columns and 13 rows depending on device orientation.
if UIDevice.current.orientation.isLandscape {
GridThatFits(items: viewModel.locationsForHorizontalOrientation, columnsCount: viewModel.height, rowCount: viewModel.width) { location in
ZStack {
RoundedRectangle(cornerRadius: 5)
imageFor(location)
}
}
} else {
GridThatFits(items: viewModel.locations, columnsCount: viewModel.width, rowCount: viewModel.height) { location in
ZStack {
RoundedRectangle(cornerRadius: 5)
imageFor(location)
}
}
}
struct GridThatFits<Item, ItemView>: View where ItemView: View, Item: Hashable {
var items: [Item]
var columnsCount: Int
var rowCount: Int
var content: (Item) -> ItemView
var body: some View {
GeometryReader { geometry in
VStack {
// 10 points padding between items
let columnsWidth = min(
(geometry.size.width - 10 * CGFloat(columnsCount + 1)) / CGFloat(columnsCount),
(geometry.size.height - 10 * CGFloat(rowCount + 1)) / CGFloat(rowCount)
)
let columns: [GridItem] = Array(repeating: .init(.fixed(columnsWidth)), count: columnsCount)
LazyVGrid(columns: columns) {
ForEach(items, id: \.self) { item in
content(item).frame(minWidth: columnsWidth, minHeight: columnsWidth)
}
}
}
}
}
}
This approach seems to cause some bug somewhere else in my code and the correct arrangement gets updated only after tapping on a square. Is there another way to implement these different grid arrangements depending on device orientation?

