The below sample code should produce a grid of RoundedRectangles inside a ScrollView. With Buttons in the NavigationBar, you can change the number of rows and columns. It works the best on the iPad, because of its bigger screen.
When you run this code, you will see (or at least, I saw) that the content of the ScrollView is not centered well. When you add some rows and columns, you can't see the topmost and leftmost ones and at the bottom and at the right there is some blank space.
Do more people experience this problem? Has anybody found a solution? Does someone know an alternative way to create a scrollable grid with flexible width and height?
import SwiftUI
struct ContentView: View {
@State var x: Int = 5
@State var y: Int = 5
var body: some View {
NavigationView {
ScrollView([.horizontal, .vertical]) {
VStack(spacing: 8) {
ForEach(0 ..< self.y, id: \.self) { yCoor in
HStack(spacing: 8) {
ForEach(0 ..< self.x, id: \.self) { xCoor in
RoundedRectangle(cornerRadius: 10)
.frame(width: 120, height: 120)
.foregroundColor(.orange)
.overlay(Text("(\(xCoor), \(yCoor))"))
}
}
}
}
.border(Color.green)
}
.border(Color.blue)
.navigationBarTitle("Contents of ScrollView misplaced", displayMode: .inline)
.navigationBarItems(
leading: HStack(spacing: 16) {
Text("x:")
.bold()
Button(action: { if self.x > 0 { self.x -= 1 } }) {
Image(systemName: "minus.circle.fill")
.imageScale(.large)
}
Button(action: { self.x += 1 }) {
Image(systemName: "plus.circle.fill")
.imageScale(.large)
}
},
trailing: HStack(spacing: 16) {
Text("y:")
.bold()
Button(action: { if self.y > 0 { self.y -= 1 } }) {
Image(systemName: "minus.circle.fill")
.imageScale(.large)
}
Button(action: { self.y += 1 }) {
Image(systemName: "plus.circle.fill")
.imageScale(.large)
}
}
)
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
Some workaround is to separate scroll view for vertical and horizontal axis.
import SwiftUI
struct Row: View {
var _y: Int
var x: Range<Int>
var body: some View {
HStack {
ForEach(x) { _x in
RoundedRectangle(cornerRadius: 10).tag(_x)
.frame(width: 120, height: 120)
.foregroundColor(.orange)
.overlay(Text("(\(_x), \(self._y))"))
}
}
}
}
struct Grid: View {
var m: Int
var n: Int
var body: some View {
ScrollView(.horizontal){
ScrollView(.vertical) {
ForEach(0 ..< n) { _y in
Row(_y: _y, x: 0 ..< self.m)
}
}
}
}
}
struct ContentView: View {
var body: some View {
VStack {
Text("Grid").font(.title)
Grid(m: 5, n: 5)
}
}
}


It is still not perfect, but usable. The best is to use only one scroll axis and fill the second direction with the right number of cells.
I miss how to know and to be able to adjust scroll position. SwiftUI is in very early stage, Once it will be more reliable, be patient
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With