iosswiftuicollectionviewuitextfieldtext-cursor

How to move cursor to next textfield automatically after fill previous textfield in Swift Collectionview cells


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.

enter image description here Any Suggestions?


Solution

  • This is the logic of moving cursor b/w textfields of OTP just map to your collectionview otp cells

         func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
        if (textField.text?.count)! < 1 && string.count > 0 {
            
            if textField == textOne {
                textTwo.becomeFirstResponder()
            }
            
            if textField == textTwo {
                textThree.becomeFirstResponder()
            }
            
            if textField == textThree {
                textFour.becomeFirstResponder()
            }
            
            if textField == textFour {
                textFive.becomeFirstResponder()
            }
            
            if textField == textFive {
                textSix.becomeFirstResponder()
            }
            
            if textField == textSix {
                textSix.resignFirstResponder()
            }
            
            textField.text = string
            return false
            
        }
        
        else if (textField.text?.count)! >= 1 && string.count == 0 {
            
            if textField == textTwo {
                textOne.becomeFirstResponder()
            }
            
            if (textField == textThree) {
                textTwo.becomeFirstResponder()
            }
            
            if (textField == textFour) {
                textThree.becomeFirstResponder()
            }
            
            if (textField == textFive) {
                textFour.becomeFirstResponder()
            }
            
            if (textField == textSix) {
                textFive.becomeFirstResponder()
            }
            
            if (textField == textOne) {
                textOne.resignFirstResponder()
            }
            
            textField.text = string
            return false
            
        }
        
        else if (textField.text?.count)! >= 1 {
            textField.text = string
            return false
        }
        
        return true
        
    }