使用自定义按钮扩展SwiftUI键盘

时间:2019-11-23 00:56:51

标签: ios xcode keyboard swiftui

我正在尝试找到一种将键或按钮添加到SwiftUI数字键盘的方法。唯一的 我发现参考文献说这是不可能的。在Swift世界中,我添加了一个工具栏 并带有按钮以关闭键盘或执行其他功能。

我什至会用顶部的按钮构建一个ZStack视图,但是我找不到添加方法。 numberPad转到我自己的视图。

在这种情况下,我真正想做的就是在数据为 输入。我首先尝试修改SceneDelegate以在点击时关闭,但是 仅当我在另一个文本或文本字段视图中而不是在该视图的开放空间中点击时才有效。

window.rootViewController = UIHostingController(rootView: contentView.onTapGesture {
    window.endEditing(true)
})

理想情况下,我将“完成”键添加到左下方。其次最好添加一个工具栏,如果 可以在SwiftUI中完成。

enter image description here

任何指导将不胜感激。

Xcode版本11.2.1(11B500)

4 个答案:

答案 0 :(得分:19)

使用UIRepresentable协议解决了该问题

 struct TestTextfield: UIViewRepresentable {
    @Binding var text: String
    var keyType: UIKeyboardType
    func makeUIView(context: Context) -> UITextField {
        let textfield = UITextField()
      textfield.keyboardType = keyType
        let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textfield.frame.size.width, height: 44))
        let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(textfield.doneButtonTapped(button:)))
        toolBar.items = [doneButton]
        toolBar.setItems([doneButton], animated: true)
        textfield.inputAccessoryView = toolBar
        return textfield
    }

    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text

    }
}

extension  UITextField{
    @objc func doneButtonTapped(button:UIBarButtonItem) -> Void {
       self.resignFirstResponder()
    }

}

在内容视图中使用

struct ContentView : View {
@State var text = ""

var body: some View {
    TestTextfield(text: $text, keyType: UIKeyboardType.phonePad)
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 50)
        .overlay(
            RoundedRectangle(cornerRadius: 16)
                .stroke(Color.blue, lineWidth: 4)
    )
}

}

答案 1 :(得分:5)

如果@Binding有问题,请实现符合UITextFieldDelegate的Coordinator类。如果需要,这将使用户能够进一步自定义TextField。

struct DecimalTextField: UIViewRepresentable {
     private var placeholder: String
     @Binding var text: String

     init(_ placeholder: String, text: Binding<String>) {
        self.placeholder = placeholder
        self._text = text
     } 

     func makeUIView(context: Context) -> UITextField {
        let textfield = UITextField()
        textfield.keyboardType = .decimalPad
        textfield.delegate = context.coordinator
        textfield.placeholder = placeholder
        let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textfield.frame.size.width, height: 44))
        let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(textfield.doneButtonTapped(button:)))
        toolBar.items = [doneButton]
        toolBar.setItems([doneButton], animated: true)
        textfield.inputAccessoryView = toolBar
        return textfield
     }

     func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
     }

     func makeCoordinator() -> Coordinator {
        Coordinator(self)
     }

     class Coordinator: NSObject, UITextFieldDelegate {
        var parent: DecimalTextField
    
     init(_ textField: DecimalTextField) {
        self.parent = textField
     }
    
     func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
         if let currentValue = textField.text as NSString? {
             let proposedValue = currentValue.replacingCharacters(in: range, with: string) as String
             self.parent.text = proposedValue
         }
         return true
     }
   }
 }

答案 2 :(得分:3)

我使用SwiftUI-Introspect库在5行中做到了!我有一个问题,可表示文本字段对填充和框架没有任何反应。一切都是通过这个库决定的!

链接:https://github.com/siteline/SwiftUI-Introspect

import SwiftUI
import Introspect

struct ContentView : View {
@State var text = ""

var body: some View {
    TextField("placeHolder", text: $text)
       .keyboardType(.default)
       .introspectTextField { (textField) in
           let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textField.frame.size.width, height: 44))
           let flexButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
           let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(textField.doneButtonTapped(button:)))
           doneButton.tintColor = .systemPink
           toolBar.items = [flexButton, doneButton]
           toolBar.setItems([flexButton, doneButton], animated: true)
           textField.inputAccessoryView = toolBar
        }
}

extension  UITextField {
   @objc func doneButtonTapped(button:UIBarButtonItem) -> Void {
      self.resignFirstResponder()
   }
}

output

答案 3 :(得分:3)

iOS 15

从 iOS 15 开始,我们可以使用新的 keyboard ToolbarItemPlacement 在键盘正上方添加自定义视图:

Form {
    ...
}
.toolbar {
    ToolbarItem(placement: .keyboard) {
        Button("Do something") {
            print("something")
        }
    }
}

您还可以将其与新的 @FocusState 属性包装器结合使用,以从当前编辑的元素中移除焦点:

@FocusState private var isFocused: Bool
...

var body: some View {
    Form {
        TextField(...)
            .focused($isFocused)
    }
    .toolbar {
        ToolbarItem(placement: .keyboard) {
            Button("Done") {
                isFocused = false
            }
        }
    }
}