Reputation: 196
I have a TextField near the top of the screen, followed by a spacer and more content below. The TextField moves outside of the screen when the keyboard is opened.
I've tried adding .ignoresSafeArea(.keyboard)
, separating the TextField from the rest of the content into two VStacks nestled in a ZStack, and a few other things found online, but nothing seems to do the trick so far.
Example:
Code to reproduce:
struct ContentView: View {
@State private var text = ""
var body: some View {
VStack {
TextField("Text", text: $text)
.font(.largeTitle.weight(.medium))
.padding()
Spacer()
VStack {
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
}
.padding()
VStack {
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
}
.padding()
}
.ignoresSafeArea(.keyboard)
}
}
Upvotes: 0
Views: 781
Reputation: 2093
After some trial and error I was able to find a way to make your textfield stay on the screen (without moving) and your texts not to move at all. I had to use a GeometryReader, that for some reason keeps the TextField in place, and a ScrollView with a custom modifier that dismisses the keyboard on drag:
struct ContentView: View {
@State private var text: String = ""
var body: some View {
GeometryReader { geometry in
ScrollView(.vertical, showsIndicators: false) {
VStack {
TextField("Text", text: $text)
.font(.largeTitle.weight(.medium))
.padding(.top)
VStack {
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
}
.padding()
VStack {
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
Text("Content")
}
.padding()
Spacer(minLength: geometry.safeAreaInsets.bottom) // Add spacer to account for safe area bottom
}
.padding()
.keyboardDismissOnDrag() // Dismiss keyboard on drag
}
}
}
}
extension View {
func keyboardDismissOnDrag() -> some View {
modifier(KeyboardDismissOnDragGesture())
}
}
struct KeyboardDismissOnDragGesture: ViewModifier {
func body(content: Content) -> some View {
content.gesture(DragGesture().onChanged { _ in
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
})
}
}
Let me know how that worked out for you!
Upvotes: 1