Search code examples
swiftswiftuiswiftui-texteditor

TextField's .focused modifier not working when "out of view" SwiftUI


I'm working with a SwiftUI List with a TextEditor at the bottom of the List. The TextEditor becomes active or "Focused" when a button is pressed.

enter image description here

To achieve this, I have added a .focused modifier to the TextEditor. When the List is scrolled to the bottom and the TextEditor is visible this works as expected and shows the keyboard when the button is pressed.

But the problem is that when the List is scrolled to the top and the TextEditor is not visible on the screen the TextField doesn't seem to get focused.

import SwiftUI


struct ContentView: View {

    var array = Array(0...20)

    @State private var newItemText : String = ""

    @FocusState var focused: Bool

    
    var body: some View {
         
            VStack{
                List{
                     ForEach(array, id: \.self) {
                         Text("\($0)")
                     }
                     
                    TextEditor(text: $newItemText)
                        .focused($focused)
                        
                }
                Button {
                    focused = true
                } label: {
                    Text("Add Item")
                }
                
            }
    }
}


Solution

  • You have to set the field in a DispatchQueue.

    import SwiftUI
    
    struct ContentView: View {
        var array = Array(0...20)
        
        @State private var newItemText : String = ""
        
        @FocusState var focusedField: Bool
        
        var body: some View {
            VStack {
                ScrollViewReader { scrollView in
                    List {
                        ForEach(array, id: \.self) {
                            Text("\($0)")
                        }
                        
                        TextField("", text: self.$newItemText)
                            .id("TextEditor")
                            .focused($focusedField)
                    }
                    Button(action: {
                        scrollView.scrollTo("TextEditor")
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                            self.focusedField = true
                        }
                    }) {
                        Text("Add Item")
                    }
                }
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    

    Hope this solves your problem!