Swift 5:如何随UITextField密码验证动态调整UIView宽与背景色?
密码验证进度条动态更新解决方案
问题核心
当前代码中每条规则分支单独设置进度条宽度,会导致后执行的规则覆盖前一条的设置,无法正确统计满足的规则总数。需要先统一统计满足数量,再据此更新进度条的宽度与颜色。
修正后的实现代码
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard let text = validationTextField.text else { return true } guard let textRange = Range(range, in: text) else { return true } let updatedText = text.replacingCharacters(in: textRange, with: string) // 禁止输入空格 if updatedText.range(of: #"\s+"#, options: .regularExpression) != nil { return false } // 统计满足的规则数量 var fulfilledRulesCount = 0 // 规则1:至少8个字符 let hasEightChars = updatedText.count >= 8 if hasEightChars { eightCharsLablel.text = "⎷ minimum of 8 characters." eightCharsLablel.textColor = #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1) fulfilledRulesCount += 1 } else { eightCharsLablel.text = "– minimum of 8 characters." eightCharsLablel.textColor = #colorLiteral(red: 0.2849253164, green: 0.1806431101, blue: 0.5, alpha: 1) } // 规则2:至少1个数字 let hasDigit = updatedText.range(of: #"\d+"#, options: .regularExpression) != nil if hasDigit { oneDigitLablel.text = "⎷ minimum 1 digit." oneDigitLablel.textColor = #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1) fulfilledRulesCount += 1 } else { oneDigitLablel.text = "– minimum 1 digit." oneDigitLablel.textColor = #colorLiteral(red: 0.2849253164, green: 0.1806431101, blue: 0.5, alpha: 1) } // 规则3:至少1个小写字母 let hasLowercase = updatedText.range(of: #".*[a-z]+.*"#, options: .regularExpression) != nil if hasLowercase { oneLowercasedLablel.text = "⎷ minimum 1 lowercased." oneLowercasedLablel.textColor = #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1) fulfilledRulesCount += 1 } else { oneLowercasedLablel.text = "– minimum 1 lowercased." oneLowercasedLablel.textColor = #colorLiteral(red: 0.2849253164, green: 0.1806431101, blue: 0.5, alpha: 1) } // 规则4:至少1个大写字母 let hasUppercase = updatedText.range(of: #".*[A-Z]+.*"#, options: .regularExpression) != nil if hasUppercase { oneUppercasedLablel.text = "⎷ minimum 1 uppercased." oneUppercasedLablel.textColor = #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1) fulfilledRulesCount += 1 } else { oneUppercasedLablel.text = "– minimum 1 uppercased." oneUppercasedLablel.textColor = #colorLiteral(red: 0.2849253164, green: 0.1806431101, blue: 0.5, alpha: 1) } // 统一更新进度条 updateValidationProgressBar(with: fulfilledRulesCount) return true } // 单独抽离进度条更新逻辑 private func updateValidationProgressBar(with fulfilledCount: Int) { let segmentWidth: CGFloat = 87 // 设置宽度:每满足一条增加一个段宽 textFieldValidLineView.frame.size.width = segmentWidth * CGFloat(fulfilledCount) // 根据满足数量匹配对应颜色 switch fulfilledCount { case 1: textFieldValidLineView.backgroundColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1) // 红色 case 2: textFieldValidLineView.backgroundColor = #colorLiteral(red: 0.9529411793, green: 0.6862745285, blue: 0.1333333403, alpha: 1) // 橙色 case 3: textFieldValidLineView.backgroundColor = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1) // 黄色 case 4: textFieldValidLineView.backgroundColor = #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1) // 绿色 default: textFieldValidLineView.frame.size.width = 0 textFieldValidLineView.backgroundColor = #colorLiteral(red: 0.2849253164, green: 0.1806431101, blue: 0.5, alpha: 1) // 初始紫色 } }
关键修改说明
- 统一统计满足数量:新增
fulfilledRulesCount变量累加满足的规则数,避免单独设置宽度导致的覆盖问题。 - 抽离更新逻辑:将进度条的宽度、颜色更新逻辑单独封装,代码更清晰易维护。
- 按数量匹配颜色:通过
switch语句对应红、橙、黄、绿四种颜色,完全匹配需求。 - 提前空格判断:把禁止空格的逻辑前置,减少无效计算。
如果需要实现四段颜色同时显示(满足4条时进度条分为红、橙、黄、绿四个分段),可以添加子View实现:
// 存储分段View的数组 private var progressSegments: [UIView] = [] // 初始化时创建四个分段 private func setupProgressSegments() { let segmentWidth: CGFloat = 87 let colors: [UIColor] = [ #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1), #colorLiteral(red: 0.9529411793, green: 0.6862745285, blue: 0.1333333403, alpha: 1), #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1), #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1) ] for i in 0..<4 { let segmentView = UIView() segmentView.frame = CGRect(x: CGFloat(i)*segmentWidth, y: 0, width: segmentWidth, height: textFieldValidLineView.frame.height) segmentView.backgroundColor = colors[i] segmentView.alpha = 0.3 // 未满足时半透明 textFieldValidLineView.addSubview(segmentView) progressSegments.append(segmentView) } } // 更新分段透明度 private func updateSegmentProgressBar(with fulfilledCount: Int) { for (index, segment) in progressSegments.enumerated() { segment.alpha = index < fulfilledCount ? 1.0 : 0.3 } }
初始化时调用setupProgressSegments(),并在代理方法中替换为updateSegmentProgressBar(with: fulfilledRulesCount)即可。
内容的提问来源于stack exchange,提问作者Gucci
相关产品推荐
相关产品推荐

