Had occasion to use a SwiftUI ScrollView
today and ran into the issue where the SwiftUI team decided to use one of the two most sensible defaults for initial presentation when the content is too large to fit in the container – center the content. This makes sense for images or maps, but not for much of anything else I am thinking of. Everything else seems to want top left (for left-to-right locales at least). Strange that something that a large percentage of people are going to want isn’t as easy to set as alignment or something, but so it goes.
Anyway, this gave me an opportunity to read up on ScrollViewReader
which, combined with the .onAppear
modifier, can get the initial presentation of a ScrollView
to the top left like so many want/need it to be.
Putting the code here so I remember for next time and in case anyone else finds a bazillion Stack Overflow posts about how ScrollView
is so hard to make display properly but no modern ScrollViewReader
answers.
//
// ContentView.swift
// trashme
//
import SwiftUI
struct ContentView : View {
var cellSize: CGFloat = 50
var numRows: Int = 30
var numCols: Int = 10
var body : some View {
VStack(alignment: .leading, spacing: 20) {
ScrollViewReader() { proxy in
ScrollView([.horizontal,.vertical], showsIndicators: true) {
HStack( alignment: .top, spacing: 0) {
VStack ( alignment: .leading, spacing: 0) {
ForEach(0 ..< numRows, id: \.self) { row in
Text("row " + row.description)
.frame( height: self.cellSize )
}
}
ForEach(0 ..< self.numCols, id: \.self) { col in
VStack( spacing: 0) {
ForEach(0 ..< self.numRows, id: \.self) { row in
Text("\(row), \(col)")
.frame( width: self.cellSize,
height: self.cellSize,
alignment: .center)
.border(.blue)
}
}
}
}
.id("root") // since our ForEach views don't really
// have true ids (\.self ~)
// we make one for the outer HStack
// in the ScrollView
}
.onAppear {
proxy.scrollTo("root", anchor: .topLeading)
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
And here’s what it looks like in an iOS SwiftUI preview pane:
