UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

How to avoid sliding/jittering soft keyboard with Textfield in List and @FocusState/.focused()

Forums > SwiftUI

I want my app to emulate the interface of apple's reminder app:

The app should set the focus to a newly created item

  1. either by clicking an "add" button regardles of the editing status on the list
  2. or by hitting the "enter" button on the soft keyboard while editing a currently selected list item.

I'm using a simple list with a custom TextField named editableListItemView which uses a firstResponderUUID of the enclosing ContentView to set the focus to the currently selected or newly created field.

The add button is working like a charm: the keyboard stays in place solidly and the cursor switches from the currently edited field to the newly created one. The onSubmit code does exibit two annoying alternative behaviors:

  1. When setting the firstResonderID to the newly created entries UUID only (isFocused not set) the keyboard slides down and up again.
  2. Setting the focus first back to the item currently submitted followed by setting the firstResponderID the keyboard stays in place but toggles briefly into CapsLock on and the back to Caps Lock off.

Here's the View with the list:

struct ContentView: View {
    @Binding var items: [TodoItem]
    @State var firstResponderUUID: UUID? = nil

     var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach($items) { $item in
                        editableListItemView(item: item, firstResponderID: $firstResponderUUID, items: $items)
                    }
                }
                Button("add without bounce") {
                    let newItem = TodoItem()
                    items.append(newItem)
                    firstResponderUUID = newItem.id
                }
            }
            .navigationTitle("Todo list")
        }
    }
}

The firstResponderUUID is handed down to the editableListItemView for setting the focus both on the list level as on the item level accordingly:

struct editableListItemView: View {
    @FocusState private var isFocused : Bool
    @StateObject var item : TodoItem
    @Binding var firstResponderID: UUID?
    @Binding var items: [TodoItem]

    var body: some View {
        TextField("Title", text: $item.title)
            .focused($isFocused)
            .task {
                isFocused = (item.id == self.firstResponderID)
            }
            .submitLabel(.go)
            .onSubmit {
                // the following line keeps the keyboard stays in place but toggles Caps-lock on/off
                isFocused = true      // with the line commented the keyboard briefly slides down and up again 
                let item1 = TodoItem()
                item1.title = "new Item from commit"
                items.append(item1)
                firstResponderID = item1.id
            }
    }

}

class TodoItem: Identifiable, ObservableObject {
    let id = UUID()
    var title: String = "untitled"
}

Any idea on how to get the keyboard stay in place and stable for the onSubmit part? Any Lead/Help appreciated. Thx.

A bit more background

  • Fully working code for my example app can be found at https://github.com/cfwdman/editableList
  • In the larger/real app the TodoItems are based on Core Data objects which are available through the object context which is passed into the view hierarchy as an environment and fetchrequest. Hence no passing/injecting of the list into the item. This is just for simplifaction of the code-
  • before isFocused became available (< iOS 15) I used the https://github.com/siteline/SwiftUI-Introspect package (with the same sliding effect) for making the TextField the firstResponder.

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.