Reputation: 2764
In my use case, I have to put a TextField
below the available items in a List
and by using that TextField
, we can add items to the List
.
Initially, there're no list items (items
array is empty)
Here's a minimal, reproducible example
import SwiftUI
struct ContentView: View {
@State var itemName = ""
@State var items = [String]()
var body: some View {
NavigationView {
List {
ForEach(self.items, id: \.self) {
Text($0)
}
VStack {
TextField("Item Name", text: $itemName)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: {
self.items.append(self.itemName)
self.itemName = ""
}) {
Text("Add Item")
}
}
}
.navigationBarTitle(Text("Title"))
}
}
}
We can add a new item to the list by typing something in the TextField
and clicking "Add Item" Button
, Every item that we add using TextField
appears above the TextField in the List
. So the TextField
goes down in the List
(Just like Apple’s Reminders app).
If the app has many items (more than 7 items), the keyboard covers the TextField
when the keyboard appears and we can’t see the TextField
.
Check this screenshot:
What I want to know is how to automatically scroll the List (move the view up) to see the TextField
when keyboard appears (like in Apple's Reminders app).
Upvotes: 19
Views: 10016
Reputation: 1184
I had a similar problem in my recent project, the easiest way for me to solve it was to wrap UITextField in SwiftUI and from my custom wrapper reach to the parent scroll view and tell it to scroll when the keyboard appears. I tried my approach on your project and it seems to work.
If you take my code for the wrapper and other files from this GitHub folder: https://github.com/LostMoa/SwiftUI-Code-Examples/tree/master/ScrollTextFieldIntoVisibleRange and then replace the SwiftUI TextField with my custom view (TextFieldWithKeyboardObserver
) then it should scroll.
import SwiftUI
struct ContentView: View {
@State var itemName = ""
@State var items = [String]()
var body: some View {
NavigationView {
List {
ForEach(self.items, id: \.self) {
Text($0)
}
VStack {
TextFieldWithKeyboardObserver(text: $itemName, placeholder: "Item Name")
Button(action: {
self.items.append(self.itemName)
self.itemName = ""
}) {
Text("Add Item")
}
}
}
.navigationBarTitle(Text("Title"))
}
}
}
I recently wrote an article explaining this solution: https://lostmoa.com/blog/ScrollTextFieldIntoVisibleRange/
Upvotes: 7