SwiftUI - 仅为一个 TextField 添加键盘工具栏按钮,将其添加到所有 TextField

Jim*_*mbo 23 swift swiftui swiftui-toolbar

背景

\n

我有两个TextFields,其中一个的键盘类型为.decimalPad.

\n

鉴于使用小数键盘关闭它时没有“完成”按钮,就像标准键盘的返回键一样,我想在小数键盘上方的工具栏中添加一个“完成”按钮在 SwiftUI 中。

\n

问题

\n

由于某种原因将 a 添加.toolbar 到 anyTextField会将其添加到所有TextFields 中!我尝试过条件修饰符,使用聚焦状态并检查值Field(但由于某种原因在检查时未设置,可能是排序的事情?)并且它仍然在两个TextFields 的键盘上方添加了工具栏。

\n

我怎样才能只.toolbar为我的单个TextField接受数字,而不为另一个TextField接受字符串?

\n

代码

\n

请注意,我尝试制作一个最小的示例,您可以将其复制并粘贴到 Xcode 中并自行运行。在 Xcode 13.2 中,为我显示 s 的键盘时存在一些问题TextField,尤其是在工作表中,因此可能需要模拟器才能正确运行它并使用 cmd+K 调出键盘。

\n
import SwiftUI\n\nstruct TestKeyboard: View {\n    @State var str: String = ""\n    @State var num: Float = 1.2\n\n    @FocusState private var focusedField: Field?\n    private enum Field: Int, CaseIterable {\n        case amount\n        case str\n    }\n\n    var body: some View {\n        VStack {\n            Spacer()\n            \n            // I'm not adding .toolbar here...\n            TextField("A text field here", text: $str)\n                .focused($focusedField, equals: .str)\n\n            // I'm only adding .toolbar here, but it still shows for the one above..\n            TextField("", value: $num, formatter: FloatNumberFormatter())\n                .keyboardType(.decimalPad)\n                .focused($focusedField, equals: .amount)\n                .toolbar {\n                    ToolbarItem(placement: .keyboard) {\n                        Button("Done") {\n                            focusedField = nil\n                        }\n                    }\n                }\n\n            Spacer()\n        }\n    }\n}\n\nclass FloatNumberFormatter: NumberFormatter {\n    override init() {\n        super.init()\n        \n        self.numberStyle = .currency        \n        self.currencySymbol = "\xe2\x82\xac"\n        self.minimumFractionDigits = 2\n        self.maximumFractionDigits = 2\n        self.locale = Locale.current\n    }\n    \n    required init?(coder: NSCoder) {\n        super.init(coder: coder)\n    }\n}\n\n// So you can preview it quickly\nstruct TestKeyboard_Previews: PreviewProvider {\n    static var previews: some View {\n        TestKeyboard()\n    }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

Asp*_*eri 8

尝试使工具栏内容有条件并将工具栏移到外部,如下所示。(现在无法测试 - 只是想法)

注:真机测试

var body: some View {
    VStack {
        Spacer()
        
        TextField("A text field here", text: $str)
            .focused($focusedField, equals: .str)

        TextField("", value: $num, formatter: FloatNumberFormatter())
            .focused($focusedField, equals: .amount)
            .keyboardType(.decimalPad)

        Spacer()
    }
    .toolbar {          // << here !!
        ToolbarItem(placement: .keyboard) {
            if field == .amount {             // << here !!
               Button("Done") {
                  focusedField = nil
               }
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 这似乎不起作用。看起来条件语句被评估了一次,并且再也没有评估过。在我的测试中,只有“field”的初始值才会使工具栏出现或不出现。 (11认同)

小智 5

我尝试了很多,但最终得到了下面的结果。

    .focused($focusedField, equals: .zip)
                .toolbar{
                    ToolbarItem(placement: .keyboard) {
                        switch focusedField{
                        case .zip:
                            HStack{
                                Spacer()
                                Button("Done"){
                                    focusedField = nil
                                }
                            }
                        default:
                                Text("")
                        }
                    }
                }
Run Code Online (Sandbox Code Playgroud)