如何在 SwiftUI 中点击 @FocusedField?

问题描述 投票:0回答:1

我是 SwiftUI 的新手,首先尝试创建一个简单的视图,让您可以使用 SwiftData 将项目添加到 NavigationStack。到目前为止,这是我的代码:

import SwiftData
import SwiftUI

struct ItemList: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var items: [Item]
    @State private var isAdding = false
    @State private var newItemName = ""
    @FocusState private var focusedField: String?
    
    var body: some View {
        NavigationStack {
            List {
                Section(header: Text("Items")) {
                    ForEach(items) { item in
                        NavigationLink {
                            Text("Placeholder")
                        } label: {
                            Text(item.name)
                        }
                        .swipeActions(edge: .trailing) {
                            Button(role: .destructive) {
                                modelContext.delete(item)
                            } label: {
                                Label("Delete Item", systemImage: "trash.fill")
                            }
                        }
                    }
                    if isAdding {
                        TextField("Title", text: $newItemTitle, onCommit: {
                            if !newItemTitle.isEmpty {
                                let newItem = Item(name: newItemTitle)
                                modelContext.insert(newItem)
                            }
                            isAdding = false
                            newItemTitle = ""
                            focusedField = nil
                        })
                        .focused($focusedField, equals: "newItem")
                        .onAppear {
                            focusedField = "newItem"
                        }
                        .onDisappear {
                            isAdding = false
                            newItemTitle = ""
                            focusedField = nil
                            appearedCount = 0
                        }
                    }
                }
            }
            .listStyle(.insetGrouped)
            .toolbar {
                ToolbarItem {
                    Button {
                        isAdding = true
                    } label: {
                        Label("New Item", systemImage: "plus")
                    }
                }
            }
        }
    }
}

#Preview {
    ItemList()
        .modelContainer(for: Item.self, inMemory: true)
}

正如您所看到的,它创建了存储在 SwiftData 中的所有项目的列表,显示为

NavigationLink
s,并且还有一个工具栏按钮可让您添加新项目。当您单击该按钮时,它会在列表底部显示一个隐藏的文本字段并将其聚焦,从而调出键盘。这部分很棒并且按预期工作。

由于

onCommit
处理程序,如果用户按键盘上的 Return 键,它将关闭文本字段(如果他们没有填写任何内容),或者在关闭字段之前创建一个新项目(如果他们已经填写) 。但缺少的是,如果用户点击文本字段之外的任何位置,它仍然保持活动状态。我希望发生的是,如果他们点击视图中该文本字段之外的任何其他位置,并且如果他们尚未输入任何内容,则应该简单地关闭文本字段。

我尝试在视图中添加 TapGesture 来执行此操作,但它不起作用,所以现在我陷入困境。我怎样才能做到这一点?

ios swift swiftui focus
1个回答
0
投票

最快的方法是使用可点击视图来

overlay
整个列表视图。这意味着当键盘显示时,可点击视图将填满整个屏幕,如果键盘隐藏则消失。你可以试试这个技巧:

List {
    ...
}
.overlay {
    Color.clear
        .contentShape(Rectangle()) //<- Added shape to make Color.clear tappable
        .frame(maxWidth: focusedField != nil ? .infinity : 0,
               maxHeight: focusedField != nil ? .infinity : 0)
        .onTapGesture {
            focusedField = nil
            isAdding = false
        }
}

© www.soinside.com 2019 - 2024. All rights reserved.