Reputation: 51
Some context: I am currently trying to create a view which contains a user-editable TextField() imbedded in a ScrollView. I want to make it where the screen automatically scrolls to the TextField when the user clicks on it to type (without being blocked by the keyboard). I figured out how to get this working by using the NavigationCenter and implementing the pseudocode view.offset(y: keyboardHeight) when the keyboard is opened.
The issue I am having is that sometimes, when the user has scrolled further down and the TextField is high on the screen, sometimes the offset causes view to over-compensate and the TextField is displaced in the area above the screen. So, you'd have to scroll again to see the TextField.
My Solution: Use 2 geometry readers to be able to determine how far down the screen the user has scrolled and adjust the offset (when the keyboard is opened) of the textfield accordingly. To do this, I have a much more complex version of the code below.
struct OverallView: View {
var body: some View {
GeometryReader { outer in
ScrollView (.vertical, showIndicators: false) {
GeometryReader { inner in
VStack {
Text("This is filler text").padding(.vertical, 100)
Text("This is filler text").padding(.vertical, 100)
Text("This is filler text").padding(.vertical, 100)
Text("This is filler text").padding(.vertical, 100)
Text("This is filler text").padding(.vertical, 100)
}
}
}
}
}
}
The Problem: Ideally, I would be able to get the minY of both the inner and outer GeometryProxies and subtract them to see how far the user has scrolled. The issue is that when I run this code, the inner GeometryReader (for a reason unknown to me) no longer allows for me to scroll. I realized this is because the height of the GeometryReader is set to the height of the screen, so when I set its height to something like 9000, I am able to scroll again. I tried setting the height of the inner Geometry Reader to the height of the outer GeometryReader, but this didn't work. I also tried various other solutions, including switching around which views were parents/childs--this, as well as my other solutions, didn't work either.
So, I wanted to know if anyone knows why this GeometryReader doesn't allow for me to scroll and how to fix it. Or, if anyone has a better approach to fix my overall problem that doesn't involve this method, I would appreciate hearing your advice.
Thank you so much for your help!
Upvotes: 5
Views: 1661
Reputation: 258345
GeometryReader
is not a regular child and you cannot use it in unknown size area (which is ScrollView), because you got into chicken-egg problem when parent-child expects size of each other.
Instead use internal geometry reader on content background, so content have defined size and you can read its position in other (global) coordinate system, like
ScrollView (.vertical, showIndicators: false) {
VStack {
Text("This is filler text").padding(.vertical, 100)
Text("This is filler text").padding(.vertical, 100)
Text("This is filler text").padding(.vertical, 100)
Text("This is filler text").padding(.vertical, 100)
Text("This is filler text").padding(.vertical, 100)
}.background(
GeometryReader { inner in
// use proxy here
})
}
Upvotes: 8