自定义验证码输入框(Swift)

需求:

如图:

验证码输入Demo.gif

思路:

视图层级:

  • 最底层一个隐藏的UITextView,上面铺的Label

  • 输入焦点在UITextView,监听UITextView的输入,给Label赋值

  • 通过Label显示输入的文字使用CAShapeLayer绘制光标

  • 通过光标的显示隐藏来控制光标的移动

  • 基础动画控制光标闪动

坑点:

  1. 用户有可能不按顺序输入。如:
    1234,此时输入光标移动到location=0来输入
  1. 用户有可能不按顺序删除。如:(支付宝注册就有此bug)
    1234,此时输入光标移动到location=1来删除
  1. 从粘贴板粘贴进来不合法的验证码。
  1. 4、光标在退后台后,返回前台,光标动画不动了

代码实现与解决方案:

一、坑点1、2、3解决方案:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    
    // 输入框已有的值
    var inputText = textView.text ?? ""
    
    if text.count == 0 { // 删除
        if range.location != inputText.count - 1 { // 删除的不是最后一个
            if inputText.count > 0 {
                // 手动删除最后一位
                textView.text.removeLast()
                textViewDidChange(textView)
            }
            return false
        }
    }
    
    if let tempRange = Range.init(range, in: inputText) {
        // 拼接输入后的值
        inputText = inputText.replacingCharacters(in: tempRange , with: text)
        let isMeet = inputText.inputValuesMeetRule(integerCount: nil, decimalCount: 0)
        if isMeet == false {
            return isMeet
        }
    }
    
    if inputText.count > inputTextNum {
        
        return false
    }
    
    return true
}

二、坑点4解决方案:

NotificationCenter.default.addObserver(self, selector: #selector(becomeActive), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(enterBack), name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil)
    
    /// 去后台
@objc fileprivate func enterBack() {
    // 移除动画
    cursor.removeAnimation(forKey: "kOpacityAnimation")
}

/// 回前台
@objc fileprivate func becomeActive() {
    // 重新添加动画
    cursor.add(opacityAnimation, forKey: "kOpacityAnimation")
}

以下是Demo链接:

https://github.com/zhongjianfeipqy/VerificationCode

你可能感兴趣的:(自定义验证码输入框(Swift))