使用 Swift 的 UITextField 中不可编辑的前缀

Uneditable prefix inside a UITextField using Swift

我在使用新的 Swift 语言在 UITextField 中创建前缀时遇到问题。目前我已经使用 Interface Builder 创建了 UITextField 并且我已经分配了一个 IBOutlet 给它,命名为 usernameField,然后使用 textFieldDidBeginEditing 函数我在里面写一个NSMutableAttributedString,命名为usernamePrefix,只包含单词"C-TAD-",最后我将UITextField最大字符数限制为13,就像这样:

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var usernameField : UITextField!

    private var usernamePrefix = NSMutableAttributedString(string: "C-TAD-")

    func textFieldDidBeginEditing(textField: UITextField) {
        if textField == usernameField {
            if usernameField.text == "" {
                usernameField.attributedText = usernamePrefix
            }
        }

        usernameField.addTarget(self, action: "textFieldDidChangeText:", forControlEvents:UIControlEvents.EditingChanged)
    }

    func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
        let maxUsernameLength = countElements(usernameField.text!) + countElements(string!) - range.length

        return maxUsernameLength <= 13
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        usernameField.delegate = self
        passwordField.delegate = self
    }
}

现在,如何为 usernamePrefix 分配新参数,以便必须为 UITextField 中写入的文本提供 2 种不同的颜色?我希望前缀在 .lightGreyColor() 中,其余部分在 .blackColor() 中。另外,我怎样才能使用户无法编辑和删除用户名前缀?

感谢您的帮助

对于第一部分,您可以重构您的委托方法,如下所示。

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    //This makes the new text black.
    textField.typingAttributes = [NSForegroundColorAttributeName:UIColor.blackColor()]
    let protectedRange = NSMakeRange(0, 6)
    let intersection = NSIntersectionRange(protectedRange, range)
    if intersection.length > 0 {

        return false
    }
    if range.location == 12 {
        return true
    }
    if range.location + range.length > 12 {
        return false
    }
    return true
}

这会将长度锁定在13,并且前缀不能被删除。输入的所有内容都将是 UIColor.blackColor()

然后你可以在你的viewDidLoad中使用类似下面的方法来设置前缀。

func makePrefix() {
    let attributedString = NSMutableAttributedString(string: "C-TAD-")
    attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.lightGrayColor(), range: NSMakeRange(0,6))
    textField.attributedText = attributedString
}

更简单的选项是设置 UITextFieldleftView 并按照您喜欢的方式自定义它:

let prefix = UILabel()
prefix.text = "C-TAD-"
// set font, color etc.
prefix.sizeToFit()

usernameField.leftView = prefix
usernameField.leftViewMode = .whileEditing // or .always

它是不可编辑和不可删除的,您不需要做任何计算来检查输入的长度。

我采用了 Jeremy 的解决方案并做了一些改进,使其更加快捷,并且还处理了用户将多个字符粘贴到文本字段中的情况。

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let protectedRange = NSRange(location: 0, length: usernamePrefix.length)
    let intersection = protectedRange.intersection(range)
    
    // prevent deleting prefix
    if intersection != nil {
        return false
    }
    
    // limit max character count
    if (textField.text ?? "").count + string.count > 13 {
        return false
    }
    
    return true
}