Implemented focusing the next text field on return key press
This commit is contained in:
parent
e7127aa88b
commit
15939d5862
|
@ -2,7 +2,10 @@ import SwiftUI
|
||||||
|
|
||||||
|
|
||||||
struct UIKitTextField: UIViewRepresentable {
|
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
|
@Binding private var text: String
|
||||||
|
|
||||||
private var placeHolder: String
|
private var placeHolder: String
|
||||||
|
@ -10,15 +13,21 @@ struct UIKitTextField: UIViewRepresentable {
|
||||||
private var keyboardType: UIKeyboardType = .default
|
private var keyboardType: UIKeyboardType = .default
|
||||||
private var isPasswordField: Bool = false
|
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
|
self.placeHolder = titleKey
|
||||||
_text = text
|
_text = text
|
||||||
|
|
||||||
self.keyboardType = keyboardType
|
self.keyboardType = keyboardType
|
||||||
self.isPasswordField = isPasswordField
|
self.isPasswordField = isPasswordField
|
||||||
|
|
||||||
|
self.focusNextTextFieldOnReturnKeyPress = focusNextTextFieldOnReturnKeyPress
|
||||||
|
|
||||||
self.actionOnReturnKeyPress = actionOnReturnKeyPress
|
self.actionOnReturnKeyPress = actionOnReturnKeyPress
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,11 +42,14 @@ struct UIKitTextField: UIViewRepresentable {
|
||||||
|
|
||||||
textField.delegate = context.coordinator
|
textField.delegate = context.coordinator
|
||||||
|
|
||||||
|
Self.NextTagId = Self.NextTagId + 1 // unbelievable, there's no ++ operator
|
||||||
|
textField.tag = Self.NextTagId
|
||||||
|
|
||||||
return textField
|
return textField
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCoordinator() -> UIKitTextField.Coordinator {
|
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>) {
|
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<UIKitTextField>) {
|
||||||
|
@ -49,12 +61,16 @@ struct UIKitTextField: UIViewRepresentable {
|
||||||
|
|
||||||
@Binding private var text: String
|
@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
|
_text = text
|
||||||
|
|
||||||
|
self.focusNextTextFieldOnReturnKeyPress = focusNextTextFieldOnReturnKeyPress
|
||||||
|
|
||||||
self.actionOnReturnKeyPress = actionOnReturnKeyPress
|
self.actionOnReturnKeyPress = actionOnReturnKeyPress
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,11 +79,18 @@ struct UIKitTextField: UIViewRepresentable {
|
||||||
}
|
}
|
||||||
|
|
||||||
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||||
actionOnReturnKeyPress?()
|
var didHandleReturnKey = actionOnReturnKeyPress?() ?? false
|
||||||
|
|
||||||
textField.resignFirstResponder()
|
if didHandleReturnKey == false && focusNextTextFieldOnReturnKeyPress == true {
|
||||||
|
let nextViewTag = textField.tag + 1
|
||||||
|
|
||||||
|
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 actionOnReturnKeyPress != nil
|
return didHandleReturnKey
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,17 +37,9 @@ struct AddAccountDialog: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
UIKitTextField("Customer ID", text: $customerId) {
|
UIKitTextField("Customer ID", text: $customerId, focusNextTextFieldOnReturnKeyPress: true, actionOnReturnKeyPress: handleReturnKeyPress)
|
||||||
if self.isRequiredDataEntered() {
|
|
||||||
self.addAccount()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UIKitTextField("Password", text: $password, isPasswordField: true) {
|
UIKitTextField("Password", text: $password, isPasswordField: true, actionOnReturnKeyPress: handleReturnKeyPress)
|
||||||
if self.isRequiredDataEntered() {
|
|
||||||
self.addAccount()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
|
@ -68,6 +60,16 @@ struct AddAccountDialog: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func handleReturnKeyPress() -> Bool {
|
||||||
|
if self.isRequiredDataEntered() {
|
||||||
|
self.addAccount()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func isRequiredDataEntered() -> Bool {
|
func isRequiredDataEntered() -> Bool {
|
||||||
return bank != nil
|
return bank != nil
|
||||||
&& customerId.isNotBlank
|
&& customerId.isNotBlank
|
||||||
|
|
|
@ -129,9 +129,12 @@ struct EnterTanDialog: View {
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
UIKitTextField("Enter TAN:", text: $enteredTan) {
|
UIKitTextField("Enter TAN:", text: $enteredTan) {
|
||||||
if self.enteredTan.isNotBlank {
|
if self.isRequiredDataEntered() {
|
||||||
self.enteringTanDone()
|
self.enteringTanDone()
|
||||||
}
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +143,7 @@ struct EnterTanDialog: View {
|
||||||
Spacer()
|
Spacer()
|
||||||
Button(action: { self.enteringTanDone() },
|
Button(action: { self.enteringTanDone() },
|
||||||
label: { Text("OK") })
|
label: { Text("OK") })
|
||||||
.disabled(self.enteredTan.isBlank)
|
.disabled( !self.isRequiredDataEntered())
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,6 +158,10 @@ struct EnterTanDialog: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func isRequiredDataEntered() -> Bool {
|
||||||
|
return self.enteredTan.isNotBlank
|
||||||
|
}
|
||||||
|
|
||||||
private func selectedTanProcedureChanged(_ changeTanProcedureTo: TanProcedure) {
|
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())
|
// 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 {
|
DispatchQueue.main.async {
|
||||||
|
|
|
@ -90,11 +90,7 @@ struct TransferMoneyDialog: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
UIKitTextField("Remittee Name", text: $remitteeName) {
|
UIKitTextField("Remittee Name", text: $remitteeName, focusNextTextFieldOnReturnKeyPress: true, actionOnReturnKeyPress: handleReturnKeyPress)
|
||||||
if self.isRequiredDataEntered() {
|
|
||||||
self.transferMoney()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onReceive(Just(remitteeName)) { newValue in
|
.onReceive(Just(remitteeName)) { newValue in
|
||||||
self.isValidRemitteeNameEntered = self.remitteeName.isNotBlank
|
self.isValidRemitteeNameEntered = self.remitteeName.isNotBlank
|
||||||
}
|
}
|
||||||
|
@ -109,11 +105,7 @@ struct TransferMoneyDialog: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UIKitTextField("Remittee IBAN", text: $remitteeIban) {
|
UIKitTextField("Remittee IBAN", text: $remitteeIban, focusNextTextFieldOnReturnKeyPress: true, actionOnReturnKeyPress: handleReturnKeyPress)
|
||||||
if self.isRequiredDataEntered() {
|
|
||||||
self.transferMoney()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onReceive(Just(remitteeIban)) { newValue in
|
.onReceive(Just(remitteeIban)) { newValue in
|
||||||
self.isValidRemitteeIbanEntered = newValue.count > 14 // TODO: implement real check if IBAN is valid
|
self.isValidRemitteeIbanEntered = newValue.count > 14 // TODO: implement real check if IBAN is valid
|
||||||
self.tryToGetBicFromIban(newValue)
|
self.tryToGetBicFromIban(newValue)
|
||||||
|
@ -121,11 +113,7 @@ struct TransferMoneyDialog: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
UIKitTextField("Amount", text: $amount, keyboardType: .decimalPad) {
|
UIKitTextField("Amount", text: $amount, keyboardType: .decimalPad, focusNextTextFieldOnReturnKeyPress: true, actionOnReturnKeyPress: handleReturnKeyPress)
|
||||||
if self.isRequiredDataEntered() {
|
|
||||||
self.transferMoney()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onReceive(Just(amount)) { newValue in
|
.onReceive(Just(amount)) { newValue in
|
||||||
// TODO: implement DecimalTextField / NumericTextField
|
// TODO: implement DecimalTextField / NumericTextField
|
||||||
let filtered = newValue.filter { "0123456789,".contains($0) }
|
let filtered = newValue.filter { "0123456789,".contains($0) }
|
||||||
|
@ -136,11 +124,7 @@ struct TransferMoneyDialog: View {
|
||||||
self.isValidAmountEntered = self.amount.isNotBlank
|
self.isValidAmountEntered = self.amount.isNotBlank
|
||||||
}
|
}
|
||||||
|
|
||||||
UIKitTextField("Usage", text: $usage) {
|
UIKitTextField("Usage", text: $usage, actionOnReturnKeyPress: handleReturnKeyPress)
|
||||||
if self.isRequiredDataEntered() {
|
|
||||||
self.transferMoney()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onReceive(Just($usage)) { newValue in
|
.onReceive(Just($usage)) { newValue in
|
||||||
self.isValidUsageEntered = true
|
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) {
|
func tryToGetBicFromIban(_ enteredIban: String) {
|
||||||
let foundBank = presenter.findUniqueBankForIban(iban: enteredIban)
|
let foundBank = presenter.findUniqueBankForIban(iban: enteredIban)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue