在 MacOS 应用程序的 SwiftUI 中管理自动建议字段中的焦点
Managing Focus in an Autosuggestion Field in SwiftUI in a MacOS App
我想在 MacOS 应用程序的 SwiftUI 中构建一个“自动建议字段”。
我的第一次尝试效果很好。
我面临的问题是管理焦点,以实现流畅的键盘(仅)处理。
如果用户在文本字段中输入了超过 1 个字符,则会显示包含建议的列表。目前用户可以用鼠标选择一个。
我想要的是,用户仍然可以编辑文本字段,使用 Cursor-Left 和 Cursor-Right 在文本字段中导航(就是这种情况),并且 另外导航 列表 Cursor-Up and Cursor-Down and select entry with e.g. Space 或 输入.
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 {[=10=].contains(input)}))
.onChange(of: input, perform: { value in
if showList == .accepted {
showList = .off}
else if input.count >= 2 {
print(
allSuggestions.filter {[=10=].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)
}
}
}
我在 NSViewRepresentable 中包装了一个 NSTextField 并使用了 NSTextFieldDelegate。你可以找到我的例子 GitHub.
我想在 MacOS 应用程序的 SwiftUI 中构建一个“自动建议字段”。
我的第一次尝试效果很好。
我面临的问题是管理焦点,以实现流畅的键盘(仅)处理。
如果用户在文本字段中输入了超过 1 个字符,则会显示包含建议的列表。目前用户可以用鼠标选择一个。
我想要的是,用户仍然可以编辑文本字段,使用 Cursor-Left 和 Cursor-Right 在文本字段中导航(就是这种情况),并且 另外导航 列表 Cursor-Up and Cursor-Down and select entry with e.g. Space 或 输入.
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 {[=10=].contains(input)}))
.onChange(of: input, perform: { value in
if showList == .accepted {
showList = .off}
else if input.count >= 2 {
print(
allSuggestions.filter {[=10=].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)
}
}
}
我在 NSViewRepresentable 中包装了一个 NSTextField 并使用了 NSTextFieldDelegate。你可以找到我的例子 GitHub.