如何设置UITextField的字母间距

时间:2015-08-07 11:47:53

标签: ios objective-c swift uitextfield

我有一个应用程序,用户必须键入一个四位数的密码。所有数字必须彼此相距一定的距离。

如果PinTextFieldUIView的子类,有没有办法做到这一点?我知道在ViewController您可以使用UITextFieldTextDidChangeNotification并为每次更改设置属性文本。通知似乎不适用于UIView

另外,我想知道如果你想设置UITextField文字的字母间距,是否有比为每次更新制作属性字符串更简单的方法?

正确的间距:

TextField with correct spacing

错误的间距:

TextField with wrong spacing

7 个答案:

答案 0 :(得分:28)

无需使用 attributedText ,说实话,修改间距是一个混乱。当我关闭键盘时,间距消失了,这促使我进一步挖掘。

每个UITextField都有一个名为 defaultTextAttributes 的属性,根据Apple "它返回一个带有默认值的文本属性字典。" Apple document也表示"此属性将指定的属性应用于文本字段的整个文本"

只需在代码中找到合适的位置,通常是在初始化文本字段的位置,然后复制并粘贴以下内容。

在Swift 3.0中回答

textfield.defaultTextAttributes.updateValue(spacing, forKey: NSKernAttributeName)

其中间距是CGFloat类型。例如2.0

这适用于不同的字体。

干杯!!

最新的语法似乎是:

 yourField.defaultTextAttributes.updateValue(36.0, 
     forKey: NSAttributedString.Key.kern)

答案 1 :(得分:9)

这是最终为每次更改设置kern的工作

    textField.addTarget(self, action: "textFieldDidChange", forControlEvents: .EditingChanged)

    func textFieldDidChange () {    
        let attributedString = NSMutableAttributedString(string: textField.text)
        attributedString.addAttribute(NSKernAttributeName, value: 5, range: NSMakeRange(0, count(textField.text)))
        attributedString.addAttribute(NSFontAttributeName, value: font, range: NSMakeRange(0, count(textField.text)))
        attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blackColor(), range: NSMakeRange(0, count(textField.text)))

        textField.attributedText = attributedString
    }

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

        if count(textField.text) < 4 {
            return true
            // Else if 4 and delete is allowed
        }else if count(string) == 0 {
            return true
            // Else limit reached
        }else{
            return false
        }
    }

然而问题仍然存在,因为不同的数字有不同的宽度,我只想回到为每个数字做一个UITextField

答案 2 :(得分:3)

使用defaultTextAttributes的{​​{1}}属性。它将为您处理转换为UITextField并应用您设置的属性。例如:

NSAttributedString

答案 3 :(得分:0)

不确定任何其他解决方案而不是使用属性字符串。

但是对于通知部分,您可以将textFields委托设置为UIView并在视图中定义以下方法。

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string; 

每次在文本字段中输入的文本发生更改时,都会调用上述方法。

答案 4 :(得分:0)

尝试此代码将委托设置为textfield.Hope后它将起作用。

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:textField.text];
    [attributedString addAttribute:NSKernAttributeName
                             value:@(5.4)
                             range:NSMakeRange(0, textField.text.length)];
    textField.attributedText = attributedString;
    return YES;
}

答案 5 :(得分:0)

这在Swift 2.2中运行良好。希望这可以帮助你在文本字段中的字母间距

override func viewDidLoad() {
 // Do any additional setup after loading the view.
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SignupVC.limitTextField(_:)), name: "UITextFieldTextDidChangeNotification", object: txtContactNumber)
}
 func limitTextField(Notif:NSNotification) {

    let limit=10;

    let attributedString = NSMutableAttributedString(string: txtContactNumber.text!)
    attributedString.addAttribute(NSKernAttributeName, value: 7, range: NSMakeRange(0, (txtContactNumber.text?.characters.count)!))
   // attributedString.addAttribute(NSFontAttributeName, value: font, range: NSMakeRange(0, count(textField.text)))
    attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blackColor(), range: NSMakeRange(0,(txtContactNumber.text?.characters.count)!))

    txtContactNumber.attributedText = attributedString
    if(txtContactNumber.text?.characters.count>limit)
    {
        txtContactNumber.text=txtContactNumber.text?.substringToIndex(limit)
    }
}

答案 6 :(得分:0)

需要计算每个字符的字距,并删除最后一个字符的字距。 Swift 5.3中有一个例子

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
    let maxLength = 6
    let symbolWidth = CGFloat(43)
    let font = UIFont.systemFont(ofSize: 30)
    
    if string == "" { // when user remove text
        return true
    }
        
    if textField.text!.count + string.count - range.length > maxLength { // when user type extra text
        return false
    }
    
    let currentText = NSMutableAttributedString(attributedString: textField.attributedText ?? NSMutableAttributedString())
    currentText.deleteCharacters(in: range) // delete selected text
    var newStringLength = 0 
    
    for char in string{
        let newSymbol = NSMutableAttributedString(string: String(char))
        newSymbol.addAttribute(.font, value: font, range: NSMakeRange(0, 1))
        let currentSymbolWidth = newSymbol.size().width
        let kern = symbolWidth - currentSymbolWidth
        newSymbol.addAttribute(.kern, value: kern, range: NSMakeRange(0,1))
        
        currentText.insert(newSymbol, at: range.location + newStringLength)
        newStringLength += 1
    }
    
    if currentText.length == maxLength{
        currentText.addAttribute(.kern, value: 0, range: NSMakeRange(maxLength - 1, 1))
    }
    
    textField.attributedText = currentText
    
    return false

}