简体   繁体   English

按下清除按钮时如何自动上一个文本字段 swiftui

[英]How to automatically previous textfield when clear button press swiftui

I am trying to create OTP screen and when the user entered the digit in the first text field and after cursor automatically move to next text field, thus functionality I got it, but I was stuck when the user removes the text in the current text field and how to automatically move to the previous text field.我正在尝试创建 OTP 屏幕,当用户在第一个文本字段中输入数字并且在 cursor 自动移动到下一个文本字段之后,我得到了它的功能,但是当用户删除当前文本字段中的文本时我被卡住了以及如何自动移动到上一个文本字段。

ScreenShot:-截屏:-

OTP屏幕

Code:-代码:-

import SwiftUI

struct VerficationCode: View {
@State private var numberOfCells: Int = 6
@State private var currentlySelectedCell = 0

var body: some View {
    HStack {
        Group {
            ForEach(0 ..< self.numberOfCells) { index in
                CharacterInputCell(currentlySelectedCell: self.$currentlySelectedCell, index: index)
            }
        }.frame(width:15,height: 56)
        .padding(.horizontal)
        .foregroundColor(.white)
        .cornerRadius(10)
        .keyboardType(.numberPad)
       }
    }
 }

struct CharacterInputCell: View {
@State private var textValue: String = ""
@Binding var currentlySelectedCell: Int

var index: Int

var responder: Bool {
    return index == currentlySelectedCell
}

var body: some View {
    CustomTextField(text: $textValue, currentlySelectedCell: $currentlySelectedCell, isFirstResponder: responder)
    }
 }

   struct CustomTextField: UIViewRepresentable {

class Coordinator: NSObject, UITextFieldDelegate {
    
    @Binding var text: String
    @Binding var currentlySelectedCell: Int
    
    var didBecomeFirstResponder = false
    
    init(text: Binding<String>, currentlySelectedCell: Binding<Int>) {
        _text = text
        _currentlySelectedCell = currentlySelectedCell
    }
    
    func textFieldDidChangeSelection(_ textField: UITextField) {
        DispatchQueue.main.async {
            self.text = textField.text ?? ""
        }
    }
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let currentText = textField.text ?? ""
        guard let stringRange = Range(range, in: currentText) else { return false }
        let updatedText = currentText.replacingCharacters(in: stringRange, with: string)
        if updatedText.count <= 1 {
            self.currentlySelectedCell += 1
        }
        return updatedText.count <= 1
    }
}

@Binding var text: String
@Binding var currentlySelectedCell: Int
var isFirstResponder: Bool = false

func makeUIView(context: UIViewRepresentableContext<CustomTextField>) -> UITextField {
    let textField = UITextField(frame: .zero)
    textField.delegate = context.coordinator
    textField.textAlignment = .center
    textField.keyboardType = .decimalPad
    return textField
}

func makeCoordinator() -> CustomTextField.Coordinator {
    return Coordinator(text: $text, currentlySelectedCell: $currentlySelectedCell)
}

func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomTextField>) {
    uiView.text = text
    if isFirstResponder && !context.coordinator.didBecomeFirstResponder  {
        uiView.becomeFirstResponder()
        context.coordinator.didBecomeFirstResponder = true
        }
     }
}

Can someone please explain to me how to back automatically when click on clear button, I've tried to implement but no results yet.有人可以向我解释如何在单击清除按钮时自动返回,我已经尝试实施但还没有结果。

Any help would be greatly appreciated.任何帮助将不胜感激。

Thanks in advance.提前致谢。

try it试试看

        import SwiftUI
    public struct PasscodeField: View {
        
        var maxDigits: Int = 6
        var label = "Enter One Time Password"
        
        @State var pin: String = ""
        @State var showPin = true
        //@State var isDisabled = false
        
        
        var handler: (String, (Bool) -> Void) -> Void
        
        public var body: some View {
            VStack{
                Text(label).font(.title)
                ZStack {
                    pinDots
                    backgroundField
                }
                showPinStack
            }
            
        }
        
        private var pinDots: some View {
            HStack {
                Spacer()
                ForEach(0..<maxDigits) { index in
                    Image(systemName: self.getImageName(at: index))
                        .font(.system(size: 60))
                    Spacer()
                }.frame(minWidth: 0, maxWidth: .infinity)
                .padding(.trailing, -24)
            }
        }
        
        private var backgroundField: some View {
            let boundPin = Binding<String>(get: { self.pin }, set: { newValue in
                self.pin = newValue
                self.submitPin()
            })
            
            return TextField("", text: boundPin, onCommit: submitPin)
          
          // Introspect library can used to make the textField become first resonder on appearing
          // if you decide to add the pod 'Introspect' and import it, comment #50 to #53 and uncomment #55 to #61
          
               .accentColor(.clear)
               .foregroundColor(.clear)
               .keyboardType(.numberPad)
               //.disabled(isDisabled)
          
    //             .introspectTextField { textField in
    //                 textField.tintColor = .clear
    //                 textField.textColor = .clear
    //                 textField.keyboardType = .numberPad
    //                 textField.becomeFirstResponder()
    //                 textField.isEnabled = !self.isDisabled
    //         }
        }
        
        private var showPinStack: some View {
            HStack {
                Spacer()
                if !pin.isEmpty {
                    showPinButton
                }
            }
            .frame(height: 100)
            .padding([.trailing])
        }
        
        private var showPinButton: some View {
            Button(action: {
                self.showPin.toggle()
            }, label: {
                self.showPin ?
                    Image(systemName: "eye.slash.fill").foregroundColor(.primary) :
                    Image(systemName: "eye.fill").foregroundColor(.primary)
            })
        }
        
        private func submitPin() {
            //guard !pin.isEmpty else {
                //showPin = false
                //return
            //}
            
            if pin.count == maxDigits {
                //isDisabled = true
                
                handler(pin) { isSuccess in
                    if isSuccess {
                        print("pin matched, go to next page, no action to perfrom here")
                    } else {
                        pin = ""
                        //isDisabled = false
                        print("this has to called after showing toast why is the failure")
                    }
                }
            }
            
            // this code is never reached under  normal circumstances. If the user pastes a text with count higher than the
            // max digits, we remove the additional characters and make a recursive call.
            if pin.count > maxDigits {
                pin = String(pin.prefix(maxDigits))
                submitPin()
            }
        }
        
        private func getImageName(at index: Int) -> String {
            if index >= self.pin.count {
                return "circle"
            }
            
            if self.showPin {
                return self.pin.digits[index].numberString + ".circle"
            }
            
            return "circle.fill"
        }
    }

    extension String {
        
        var digits: [Int] {
            var result = [Int]()
            
            for char in self {
                if let number = Int(String(char)) {
                    result.append(number)
                }
            }
            
            return result
        }
        
    }

    extension Int {
        
        var numberString: String {
            
            guard self < 10 else { return "0" }
            
            return String(self)
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM