From c08b4e7b5d18d5d9d092eb10cdd23944de6e3d79 Mon Sep 17 00:00:00 2001 From: dankito Date: Sat, 5 Sep 2020 15:44:14 +0200 Subject: [PATCH] Implemented adding 'Done' button to keyboard as numeric keyboards don't have one -> keyboard cannot be dismissed --- .../ui/LabelledUIKitTextField.swift | 6 ++- .../BankingiOSApp/ui/UIKitTextField.swift | 43 ++++++++++++++++++- .../ui/views/EnterTanDialog.swift | 3 +- .../ui/views/TransferMoneyDialog.swift | 3 +- 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/ui/BankingiOSApp/BankingiOSApp/ui/LabelledUIKitTextField.swift b/ui/BankingiOSApp/BankingiOSApp/ui/LabelledUIKitTextField.swift index b4f8c7d4..c3ba94bc 100644 --- a/ui/BankingiOSApp/BankingiOSApp/ui/LabelledUIKitTextField.swift +++ b/ui/BankingiOSApp/BankingiOSApp/ui/LabelledUIKitTextField.swift @@ -11,6 +11,8 @@ struct LabelledUIKitTextField: View { var keyboardType: UIKeyboardType = .default var autocapitalizationType: UITextAutocapitalizationType = .sentences + var addDoneButton: Bool = false + var isPasswordField: Bool = false var focusOnStart = false @@ -46,7 +48,9 @@ struct LabelledUIKitTextField: View { Spacer() - UIKitTextField(placeholder, text: $text, keyboardType: keyboardType, autocapitalizationType: autocapitalizationType, isPasswordField: isPasswordField, + UIKitTextField(placeholder, text: $text, + keyboardType: keyboardType, autocapitalizationType: autocapitalizationType, addDoneButton: addDoneButton, + isPasswordField: isPasswordField, focusOnStart: focusOnStart, focusNextTextFieldOnReturnKeyPress: focusNextTextFieldOnReturnKeyPress, focusTextField: focusTextFieldBinding, isFocusedChanged: isFocusedChanged, textAlignment: .right, isUserInputEnabled: isUserInputEnabled, actionOnReturnKeyPress: actionOnReturnKeyPress, textChanged: textChanged) diff --git a/ui/BankingiOSApp/BankingiOSApp/ui/UIKitTextField.swift b/ui/BankingiOSApp/BankingiOSApp/ui/UIKitTextField.swift index b7c67d3c..8bd0f018 100644 --- a/ui/BankingiOSApp/BankingiOSApp/ui/UIKitTextField.swift +++ b/ui/BankingiOSApp/BankingiOSApp/ui/UIKitTextField.swift @@ -12,6 +12,8 @@ struct UIKitTextField: UIViewRepresentable { private var keyboardType: UIKeyboardType = .default private var autocapitalizationType: UITextAutocapitalizationType = .sentences + private var addDoneButton: Bool = false + private var isPasswordField: Bool = false private var focusOnStart = false @@ -28,16 +30,19 @@ struct UIKitTextField: UIViewRepresentable { private var textChanged: ((String) -> Void)? = nil - init(_ titleKey: String, text: Binding, keyboardType: UIKeyboardType = .default, autocapitalizationType: UITextAutocapitalizationType = .sentences, + init(_ titleKey: String, text: Binding, keyboardType: UIKeyboardType = .default, autocapitalizationType: UITextAutocapitalizationType = .sentences, addDoneButton: Bool = false, isPasswordField: Bool = false, focusOnStart: Bool = false, focusNextTextFieldOnReturnKeyPress: Bool = false, focusTextField: Binding = .constant(false), isFocusedChanged: ((Bool) -> Void)? = nil, textAlignment: NSTextAlignment = .natural, isUserInputEnabled: Bool = true, actionOnReturnKeyPress: (() -> Bool)? = nil, textChanged: ((String) -> Void)? = nil) { + self.placeholder = titleKey _text = text self.keyboardType = keyboardType self.autocapitalizationType = autocapitalizationType + self.addDoneButton = addDoneButton + self.isPasswordField = isPasswordField self.focusOnStart = focusOnStart @@ -58,9 +63,14 @@ struct UIKitTextField: UIViewRepresentable { textField.placeholder = placeholder.localize() + textField.isSecureTextEntry = isPasswordField + textField.keyboardType = keyboardType textField.autocapitalizationType = autocapitalizationType - textField.isSecureTextEntry = isPasswordField + + if addDoneButton { + addDoneButtonToKeyboard(textField, context.coordinator) + } textField.delegate = context.coordinator @@ -89,6 +99,21 @@ struct UIKitTextField: UIViewRepresentable { } } + private func addDoneButtonToKeyboard(_ textField: UITextField, _ coordinator: Coordinator) { + coordinator.textField = textField + + let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: coordinator, action: #selector(coordinator.doneButtonTapped)) + + let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50)) + doneToolbar.barStyle = .default + + doneToolbar.items = [spacer, doneButton] + doneToolbar.sizeToFit() + + textField.inputAccessoryView = doneToolbar + } + func makeCoordinator() -> UIKitTextField.Coordinator { return Coordinator(text: $text, focusNextTextFieldOnReturnKeyPress: focusNextTextFieldOnReturnKeyPress, isFocusedChanged: isFocusedChanged, @@ -109,6 +134,8 @@ struct UIKitTextField: UIViewRepresentable { private var actionOnReturnKeyPress: (() -> Bool)? private var textChanged: ((String) -> Void)? + + var textField: UITextField? = nil init(text: Binding, focusNextTextFieldOnReturnKeyPress: Bool, isFocusedChanged: ((Bool) -> Void)? = nil, isUserInputEnabled: Bool, @@ -153,6 +180,11 @@ struct UIKitTextField: UIViewRepresentable { } func textFieldShouldReturn(_ textField: UITextField) -> Bool { + return handleReturnKeyPress(textField) + } + + @discardableResult + func handleReturnKeyPress(_ textField: UITextField) -> Bool { var didHandleReturnKey = actionOnReturnKeyPress?() ?? false if didHandleReturnKey == false && focusNextTextFieldOnReturnKeyPress == true { @@ -170,6 +202,13 @@ struct UIKitTextField: UIViewRepresentable { return didHandleReturnKey } + + @objc + func doneButtonTapped() { + if let textField = self.textField { + handleReturnKeyPress(textField) + } + } } diff --git a/ui/BankingiOSApp/BankingiOSApp/ui/views/EnterTanDialog.swift b/ui/BankingiOSApp/BankingiOSApp/ui/views/EnterTanDialog.swift index 567cc951..cf77390d 100644 --- a/ui/BankingiOSApp/BankingiOSApp/ui/views/EnterTanDialog.swift +++ b/ui/BankingiOSApp/BankingiOSApp/ui/views/EnterTanDialog.swift @@ -109,7 +109,8 @@ struct EnterTanDialog: View { .padding(.vertical, 2) Section { - LabelledUIKitTextField(label: "Enter TAN:", text: $enteredTan, keyboardType: tanChallenge.tanProcedure.isNumericTan ? .numberPad : .default, autocapitalizationType: .none, actionOnReturnKeyPress: { + LabelledUIKitTextField(label: "Enter TAN:", text: $enteredTan, keyboardType: tanChallenge.tanProcedure.isNumericTan ? .numberPad : .default, + autocapitalizationType: .none, addDoneButton: tanChallenge.tanProcedure.isNumericTan, actionOnReturnKeyPress: { if self.isRequiredDataEntered() { self.enteringTanDone() return true diff --git a/ui/BankingiOSApp/BankingiOSApp/ui/views/TransferMoneyDialog.swift b/ui/BankingiOSApp/BankingiOSApp/ui/views/TransferMoneyDialog.swift index 91dfe965..600b6c01 100644 --- a/ui/BankingiOSApp/BankingiOSApp/ui/views/TransferMoneyDialog.swift +++ b/ui/BankingiOSApp/BankingiOSApp/ui/views/TransferMoneyDialog.swift @@ -146,7 +146,8 @@ struct TransferMoneyDialog: View { } Section { - LabelledUIKitTextField(label: "Amount", text: $amount, keyboardType: .decimalPad, focusNextTextFieldOnReturnKeyPress: true, actionOnReturnKeyPress: handleReturnKeyPress, textChanged: checkAndValidateEnteredAmount) + LabelledUIKitTextField(label: "Amount", text: $amount, keyboardType: .decimalPad, addDoneButton: true, + focusNextTextFieldOnReturnKeyPress: true, actionOnReturnKeyPress: handleReturnKeyPress, textChanged: checkAndValidateEnteredAmount) amountValidationResult.map { validationError in ValidationLabel(validationError)