18

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).

LinusGeffarth
  • 27,197
  • 29
  • 120
  • 174
umayanga
  • 2,254
  • 3
  • 15
  • 26
  • One thing you could do (dodging your question here) is to move the text field somewhere else. That might solve this case, but obviously doesn't solve the greater issue about moving stuff to respect the keyboard. – LinusGeffarth Sep 17 '19 at 13:21
  • This might be help you: https://stackoverflow.com/questions/57753060/keyboard-listener-in-list-in-swiftui/57754624#57754624 – Sagar Chauhan Sep 17 '19 at 13:40
  • see here as well: https://stackoverflow.com/questions/56716311/how-to-show-complete-list-when-keyboard-is-showing-up-in-swiftui – Andre Carrera Sep 17 '19 at 21:13
  • Possible duplicate of [Move TextField up when thekeyboard has appeared by using SwiftUI? : iOS](https://stackoverflow.com/questions/56491881/move-textfield-up-when-thekeyboard-has-appeared-by-using-swiftui-ios) – Gene Z. Ragan Oct 15 '19 at 20:48
  • I tried few different approaches, and what worked for me in the end is https://stackoverflow.com/a/60178361/4189037 – Predrag Samardzic Feb 11 '20 at 22:34

1 Answers1

7

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/

Natalia Panferova
  • 1,134
  • 7
  • 9
  • Thanks very much for this! Excellent answer and great article too. I think SwiftUI needs a better way of handling this, and until then, wrapping a UIKitTextField is the best way to go in my opinion - having tried a lot of solutions. Thanks again! – Dan Barclay Feb 20 '20 at 17:36
  • this is the best answer so far for handling UITextField with List or ScrollView, I have used your approach to move a UITextView up while the user typing where the UITextView expands in height (doesn't scroll) according to the entered text – JAHelia Feb 24 '20 at 12:52
  • Brilliant idea! Nice blog post too. – Brett Apr 01 '20 at 03:25
  • 1
    I'm trying to use this solution since it works very well, but using the custom textfield disables all other swiftui methods you can call to a regular textfield, such as ```.keyboardType()```, ```multilineTextAlignment()```, etc. Is there a way around this? – Amin Apr 13 '20 at 22:11
  • This is the best solution and should be marked as acccepted answer – Di Nerd Apps May 26 '20 at 19:06