I want to build an "autosuggestion field" in SwiftUI in a MacOS App.
My first attempts work quite OK.
The problem I face is managing the focus, to enable smooth keyboard (only) handling.
If the users has entered more than 1 char in the textfield, a list with suggestions is displayed. At the moment the user can choose one with the mouse.
What I want is, that the user can still edit the textfield, navigate in the textfield with Cursor-Left and Cursor-Right (which is the case) and additionally navigate the list with Cursor-Up and Cursor-Down and select an entry with e.g. Space or Enter.
struct TestSearchField2: View {
var body: some View {
VStack{
SearchField2()
} .frame(width: 400, height: 400, alignment: .center)
}
}
enum SuggestionListStatus {
case off
case on
case accepted
}
struct SearchField2: View {
let allSuggestions = ["michael Schneider","thomas mueller","joachim Oster","Dennis mueller","Michael Carter","frank 1","frank 2","frank 3","frank 4","frank 5"]
@State var input = ""
@State var showList : SuggestionListStatus = .off
@State var selected = ""
var body: some View {
TextField("input Data", text: $input)
.cornerRadius(5.0)
.overlay(SuggestionList2(suggestionListStatus: $showList, selected: $input, suggestions: allSuggestions.filter {$0.contains(input)}))
.onChange(of: input, perform: { value in
if showList == .accepted {
showList = .off}
else if input.count >= 2 {
print(
allSuggestions.filter {$0.contains(input)})
showList = .on
} else {
showList = .off
}
})
}
}
struct SuggestionList2: View {
@Binding var suggestionListStatus : SuggestionListStatus
@Binding var selected : String
@State var selection : String? = "Michael"
var suggestions : [String]
var body: some View {
if suggestionListStatus == .on {
VStack{
List(suggestions, id: \.self, selection: $selection){ s in
Text(s).onTapGesture {
print("Pressed; \(s)")
selected = s
suggestionListStatus = .accepted
}
}
Text("Debug setected: \(selection ?? "nothing selected")").font(.footnote)
}
.frame(width: 200, height: 150, alignment: .leading)
.offset(x: 0, y: 100)
}
}
}
I wrapped a NSTextField in NSViewRepresentable and used the NSTextFieldDelegate. You can find my example of GitHub.