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).
Moving SwiftUI View Up When Keyboard Appears Create keyboard height state. SwiftUI will automatically update the view whenever the keyboard height changes. Add padding to the bottom of the view, which will make it move up and down with the keyboard.
Using this protocol, KeyboardReadable , you can conform to any View and get keyboard updates from it. It works by using Combine and creating a publisher so we can receive the keyboard notifications. You can now read from the isKeyboardVisible variable to know if the keyboard is visible.
Pure SwiftUI (iOS 15) To dismiss the keyboard, simply set view's focusedField to nil . The return key will dismiss keyboard automatically (since iOS 14).
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/
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