I am working on Swift application, In that I have OTP verification screen.
So, User can enters 6 digits otp in 6 textfields.
I have created collection view and in that cell I have added dynamically 6 cells.
I am able to entering text and validating.
But, My requirement is once first digit fills, automatically cursor should move to next one.
My code is below
var insertedValues = [String]()
private var arrayOfCells: [OtpCollectionViewCell] = []
override func viewDidLoad() {
super.viewDidLoad()
let cellSize = CGSize(width:50 , height:50)
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //.horizontal
layout.itemSize = cellSize
layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
layout.minimumLineSpacing = 1.0
layout.minimumInteritemSpacing = 1.0
collectionView.setCollectionViewLayout(layout, animated: true)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 6 // this may be dynamic count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OtpCollectionViewCell", for: indexPath) as! OtpCollectionViewCell
cell.otpTextField.tag = indexPath.row
cell.otpTextField.delegate = self
arrayOfCells += [cell]
return cell
}
func textFieldDidEndEditing(_ textField: UITextField) {
if insertedValues.count > 0 {
insertedValues.removeAll()
}
for i in 0..<arrayOfCells.count {
if let textfieldText = arrayOfCells[i].otpTextField.text, textfieldText != "" {
insertedValues.append(textfieldText)
if insertedValues.count == 6 {
textField.resignFirstResponder()
self.performAPICall()
}
}
}
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if range.location == 0 && string == " " { //restrict single and double space tap
return false
}
let currentCharacterCount = textField.text?.count ?? 0
if range.length + range.location > currentCharacterCount {
return false
}
let newLength = currentCharacterCount + string.count - range.length
return newLength <= 1
}
Here is my screen looks like.
2
Answers
I have followed above solution, But, there is much code if there are more otp textfields. So, I have optimised solution.
Because in future, We may increase OTP textfields count like 10, 12. So, that is the purpose, I followed dynamic cells(Textfields) using collection view.
Here is my code
This code is working as I expected!
This is the logic of moving cursor b/w textfields of OTP just map to your collectionview otp cells