[英]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:-截屏:-
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.