You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 10:15:40