[ad_1]
I want to build a signup screen in which user needs to input date of birth in DD MM YYYY format, something like the image below.
I’m creating a single enum for input textfields and the code looks like
struct Test: View {
@StateObject var testViewModel: TestViewModel = .init()
@FocusState var activeField: BirthdayFields?
var body: some View {
ZStack {
Color.black.ignoresSafeArea()
VStack {
Spacer()
BirthdayField()
.padding()
Button{Task {await testViewModel.letsDate()}}
label: {
Text("Birthday")
.keyboardType(.numberPad)
.padding()
.frame(maxWidth: .infinity)
.background{
RoundedRectangle(cornerRadius: 10, style: .continuous)
.fill(.yellow)
}
}
.disabled(checkStates())
.opacity(checkStates() ? 0.4 : 1)
Spacer()
}
.onChange(of: testViewModel.dobFields) { newValue in
DOBConditions(value: newValue)
}
}
}
@ViewBuilder
func BirthdayField() -> some View {
HStack(spacing: 6) {
ForEach(0..<8, id: \.self) { index in
VStack {
TextField("D", text: $testViewModel.dobFields[index])
.foregroundColor(.gray)
.keyboardType(.numberPad)
.textContentType(.dateTime)
.multilineTextAlignment(.center)
.focused($activeField, equals: activeStateForIndex(index: index))
.onAppear{
DispatchQueue.main.async {
activeField = activeStateForIndex(index: index)
}
}
Rectangle()
.fill(activeField == activeStateForIndex(index: index) ? .blue : .gray.opacity(0.4))
.frame( height: 4)
}
}
}
}
func checkStates() -> Bool {
for index in 0..<8{
if testViewModel.dobFields[index].isEmpty{return true}
}
return false
}
func activeStateForIndex(index: Int) -> BirthdayFields {
switch index {
case 0: return .field1
case 1: return .field2
case 2: return .field3
case 3: return .field4
case 4: return .field5
case 5: return .field6
case 6: return .field7
default: return .field8
}
}
enum BirthdayFields {
case field1
case field2
case field3
case field4
case field5
case field6
case field7
case field8
}
func DOBConditions(value: [String]) {
for index in 0..<8{
if value[index].count == 8{
DispatchQueue.main.async {
testViewModel.dobText = value[index]
testViewModel.dobFields[index] = ""
}
return
}
}
// moving next field if current field type
for index in 0..<7{
if value[index].count == 1 && activeStateForIndex(index: index) == activeField {
activeField = activeStateForIndex(index: index + 1)
}
}
// moving back if current is empty and previous is not empty
for index in 1...7{
if value[index].isEmpty && !value[index - 1].isEmpty{
activeField = activeStateForIndex(index: index - 1)
}
}
// limiting only one text
for index in 0..<8{
if value[index].count > 1{
testViewModel.dobFields[index] = String(value[index].last!)
}
}
}
}
The result looks like below image
My question is, how can I achieve the DD MM YYYY format? Should I create separate enums for date, month, and year? And how does moving to next field or deleting the previous ones work in that case?
[ad_2]