【问题标题】:How to set letter spacing of UITextField如何设置 UITextField 的字母间距
【发布时间】:2015-10-30 20:31:58
【问题描述】:

我有一个应用程序,用户必须在其中输入一个四位数的密码。所有数字之间必须保持一定的距离。

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

我还想知道,如果您想设置UITextField 文本的字母间距,是否有比为每次更新创建属性字符串更简单的方法?

正确的间距:

间距错误:

【问题讨论】:

  • 开头*你必须使用等宽字体!!!!!!
  • 对于任何在这里搜索的人来说,自从这个老问题以来,这已经发生了巨大的变化。 请勿使用属性文本。解决方案非常简单——看看下面@iOSer 的答案。
  • 间距很简单,数字下面的线怎么画?
  • @Vakas 我有同样的问题你找到解决方案了吗

标签: ios objective-c swift uitextfield


【解决方案1】:

没有必要使用 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)

【讨论】:

  • @Fattie 感谢您添加最新的语法和评论。 :)
  • 如果 TextField 是安全的,则此解决方案不起作用。
  • @Soumen 对不起,我最近忙于项目。但是,一旦有时间,我肯定会尽快调查。顺便说一句,感谢您指出这一点
  • 如何从最后一个文本中删除空格。我只需要喂4位数。在那种情况下它会出错。
  • @Ashu 所以你想让三个数字等距,最后一个数字不是这样吗?不知道你是什么意思
【解决方案2】:

这是最终为每次更改设置紧排的方法

    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

【讨论】:

  • 正确的解决方案是使用等宽字体。
【解决方案3】:

使用UITextFielddefaultTextAttributes 属性。它将为您处理到NSAttributedString 的转换并应用您设置的属性。例如:

    NSMutableDictionary *attrs = [self.textField.defaultTextAttributes mutableCopy];
[attrs addEntriesFromDictionary:@{
    NSKernAttributeName: @18,
    NSUnderlineColorAttributeName: [UIColor grayColor],
    NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle | NSUnderlinePatternDash)
}];
self.textField.defaultTextAttributes = attrs;

【讨论】:

    【解决方案4】:

    在将委托设置为文本字段后尝试此代码。希望它会起作用。

    - (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;
    }
    

    【讨论】:

    • shouldChangeCharactersInRange 不适用于第一个字母,它只会在您输入第二个字母后出现。
    • 查看此链接以了解首字母更改,它可能对您有所帮助:stackoverflow.com/questions/7010547/…
    【解决方案5】:

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

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

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

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

    【讨论】:

      【解决方案6】:

      这在 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)
          }
      }
      

      【讨论】:

        【解决方案7】:

        需要计算每个字符的紧排并删除最后一个字符。 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
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-04
          • 1970-01-01
          • 2020-02-20
          • 1970-01-01
          • 2021-09-18
          • 1970-01-01
          相关资源
          最近更新 更多