Implemented focusing the next text field on return key press

This commit is contained in:
dankito 2020-07-29 13:18:45 +02:00
parent e7127aa88b
commit 15939d5862
4 changed files with 69 additions and 42 deletions

View File

@ -3,6 +3,9 @@ import SwiftUI
struct UIKitTextField: UIViewRepresentable {
static private var NextTagId = 234567 // start at a high, very unlikely number to not interfere with manually set tags
@Binding private var text: String
private var placeHolder: String
@ -10,15 +13,21 @@ struct UIKitTextField: UIViewRepresentable {
private var keyboardType: UIKeyboardType = .default
private var isPasswordField: Bool = false
private var actionOnReturnKeyPress: (() -> Void)? = nil
private var focusNextTextFieldOnReturnKeyPress = false
init(_ titleKey: String, text: Binding<String>, keyboardType: UIKeyboardType = .default, isPasswordField: Bool = false, actionOnReturnKeyPress: (() -> Void)? = nil) {
private var actionOnReturnKeyPress: (() -> Bool)? = nil
init(_ titleKey: String, text: Binding<String>, keyboardType: UIKeyboardType = .default, isPasswordField: Bool = false,
focusNextTextFieldOnReturnKeyPress: Bool = false, actionOnReturnKeyPress: (() -> Bool)? = nil) {
self.placeHolder = titleKey
_text = text
self.keyboardType = keyboardType
self.isPasswordField = isPasswordField
self.focusNextTextFieldOnReturnKeyPress = focusNextTextFieldOnReturnKeyPress
self.actionOnReturnKeyPress = actionOnReturnKeyPress
}
@ -33,11 +42,14 @@ struct UIKitTextField: UIViewRepresentable {
textField.delegate = context.coordinator
Self.NextTagId = Self.NextTagId + 1 // unbelievable, there's no ++ operator
textField.tag = Self.NextTagId
return textField
}
func makeCoordinator() -> UIKitTextField.Coordinator {
return Coordinator(text: $text, actionOnReturnKeyPress: actionOnReturnKeyPress /*, nextResponder: $nextResponder, isResponder: $isResponder */)
return Coordinator(text: $text, focusNextTextFieldOnReturnKeyPress: focusNextTextFieldOnReturnKeyPress, actionOnReturnKeyPress: actionOnReturnKeyPress)
}
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<UIKitTextField>) {
@ -49,12 +61,16 @@ struct UIKitTextField: UIViewRepresentable {
@Binding private var text: String
private var actionOnReturnKeyPress: (() -> Void)?
private var focusNextTextFieldOnReturnKeyPress: Bool
private var actionOnReturnKeyPress: (() -> Bool)?
init(text: Binding<String>, actionOnReturnKeyPress: (() -> Void)? = nil) {
init(text: Binding<String>, focusNextTextFieldOnReturnKeyPress: Bool, actionOnReturnKeyPress: (() -> Bool)? = nil) {
_text = text
self.focusNextTextFieldOnReturnKeyPress = focusNextTextFieldOnReturnKeyPress
self.actionOnReturnKeyPress = actionOnReturnKeyPress
}
@ -63,11 +79,18 @@ struct UIKitTextField: UIViewRepresentable {
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
actionOnReturnKeyPress?()
var didHandleReturnKey = actionOnReturnKeyPress?() ?? false
textField.resignFirstResponder()
if didHandleReturnKey == false && focusNextTextFieldOnReturnKeyPress == true {
let nextViewTag = textField.tag + 1
return actionOnReturnKeyPress != nil
let nextView = textField.superview?.superview?.superview?.viewWithTag(nextViewTag)
?? textField.superview?.superview?.superview?.superview?.superview?.viewWithTag(nextViewTag) // for text fields in Lists (tables)
didHandleReturnKey = nextView?.becomeFirstResponder() ?? false
}
return didHandleReturnKey
}
}

View File

@ -37,17 +37,9 @@ struct AddAccountDialog: View {
}
Section {
UIKitTextField("Customer ID", text: $customerId) {
if self.isRequiredDataEntered() {
self.addAccount()
}
}
UIKitTextField("Customer ID", text: $customerId, focusNextTextFieldOnReturnKeyPress: true, actionOnReturnKeyPress: handleReturnKeyPress)
UIKitTextField("Password", text: $password, isPasswordField: true) {
if self.isRequiredDataEntered() {
self.addAccount()
}
}
UIKitTextField("Password", text: $password, isPasswordField: true, actionOnReturnKeyPress: handleReturnKeyPress)
}
Section {
@ -68,6 +60,16 @@ struct AddAccountDialog: View {
}
func handleReturnKeyPress() -> Bool {
if self.isRequiredDataEntered() {
self.addAccount()
return true
}
return false
}
func isRequiredDataEntered() -> Bool {
return bank != nil
&& customerId.isNotBlank

View File

@ -129,9 +129,12 @@ struct EnterTanDialog: View {
Section {
UIKitTextField("Enter TAN:", text: $enteredTan) {
if self.enteredTan.isNotBlank {
if self.isRequiredDataEntered() {
self.enteringTanDone()
return true
}
return false
}
}
@ -140,7 +143,7 @@ struct EnterTanDialog: View {
Spacer()
Button(action: { self.enteringTanDone() },
label: { Text("OK") })
.disabled(self.enteredTan.isBlank)
.disabled( !self.isRequiredDataEntered())
Spacer()
}
}
@ -155,6 +158,10 @@ struct EnterTanDialog: View {
}
private func isRequiredDataEntered() -> Bool {
return self.enteredTan.isNotBlank
}
private func selectedTanProcedureChanged(_ changeTanProcedureTo: TanProcedure) {
// do async as at this point Picker dialog gets dismissed -> this EnterTanDialog would never get dismissed (and dismiss has to be called before callback.changeTanProcedure())
DispatchQueue.main.async {

View File

@ -90,11 +90,7 @@ struct TransferMoneyDialog: View {
}
Section {
UIKitTextField("Remittee Name", text: $remitteeName) {
if self.isRequiredDataEntered() {
self.transferMoney()
}
}
UIKitTextField("Remittee Name", text: $remitteeName, focusNextTextFieldOnReturnKeyPress: true, actionOnReturnKeyPress: handleReturnKeyPress)
.onReceive(Just(remitteeName)) { newValue in
self.isValidRemitteeNameEntered = self.remitteeName.isNotBlank
}
@ -109,11 +105,7 @@ struct TransferMoneyDialog: View {
}
}
UIKitTextField("Remittee IBAN", text: $remitteeIban) {
if self.isRequiredDataEntered() {
self.transferMoney()
}
}
UIKitTextField("Remittee IBAN", text: $remitteeIban, focusNextTextFieldOnReturnKeyPress: true, actionOnReturnKeyPress: handleReturnKeyPress)
.onReceive(Just(remitteeIban)) { newValue in
self.isValidRemitteeIbanEntered = newValue.count > 14 // TODO: implement real check if IBAN is valid
self.tryToGetBicFromIban(newValue)
@ -121,11 +113,7 @@ struct TransferMoneyDialog: View {
}
Section {
UIKitTextField("Amount", text: $amount, keyboardType: .decimalPad) {
if self.isRequiredDataEntered() {
self.transferMoney()
}
}
UIKitTextField("Amount", text: $amount, keyboardType: .decimalPad, focusNextTextFieldOnReturnKeyPress: true, actionOnReturnKeyPress: handleReturnKeyPress)
.onReceive(Just(amount)) { newValue in
// TODO: implement DecimalTextField / NumericTextField
let filtered = newValue.filter { "0123456789,".contains($0) }
@ -136,11 +124,7 @@ struct TransferMoneyDialog: View {
self.isValidAmountEntered = self.amount.isNotBlank
}
UIKitTextField("Usage", text: $usage) {
if self.isRequiredDataEntered() {
self.transferMoney()
}
}
UIKitTextField("Usage", text: $usage, actionOnReturnKeyPress: handleReturnKeyPress)
.onReceive(Just($usage)) { newValue in
self.isValidUsageEntered = true
}
@ -174,6 +158,17 @@ struct TransferMoneyDialog: View {
}
func handleReturnKeyPress() -> Bool {
if self.isRequiredDataEntered() {
self.transferMoney()
return true
}
return false
}
func tryToGetBicFromIban(_ enteredIban: String) {
let foundBank = presenter.findUniqueBankForIban(iban: enteredIban)