最大输入后禁用 UITextField 光标移动

Posted

技术标签:

【中文标题】最大输入后禁用 UITextField 光标移动【英文标题】:Disable UITextField cursor movement after max input 【发布时间】:2019-10-14 05:38:29 【问题描述】:

我为固定大小的输入创建了一个自定义 UITextField 组件。 TextField 的宽度、字体大小、字距和字符数都是固定的。我可以阻止用户输入超过 8 个字符(参见下面的 shouldChangeCharactersIn 方法),但是在第 8 个字符之后,光标会自动移动到下一个位置,这会产生以下问题。

我想显示所有输入的字符而不减小它们的大小。所以

[ 1 2 3 4 5 6 7 8 ] 应该显示而不是 [ 2 3 4 5 6 7 8 | ]

我试图将光标放在第 8 个字符的右侧,但这会改变所有字距并影响所有其他字符。

处理这个问题的正确方法是什么?我应该如何防止光标移动,以使 UITextField 不会向右滚动?

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool 
    guard let textFieldText = textField.text,
        let rangeOfTextToReplace = Range(range, in: textFieldText),
        !string.containsSpecialCharacters else 
            return false
    
    let substringToReplace = textFieldText[rangeOfTextToReplace]
    let count = textFieldText.count - substringToReplace.count + string.count

    return count <= 8

【问题讨论】:

试试这个guard let currentText = (textField.text as NSString?)?.replacingCharacters(in: range, with: string) else return true let newLength = currentText.count + string.count - range.length return newLength &lt;= 8 这会阻止第 8 个字符的输入。我想允许 8 个字符,那么光标不应该移动到下一个空格。 【参考方案1】:

我通过更改最后一个字符后的紧排来解决了这个问题。所以现在,光标不再跳 40pt,而是只跳 1pt(或者你在下面的方法中设置的任何东西)

@objc private func textFieldDidChange() 

    guard let text = textField.text else  return 

    if text.count == Constant.deviceCodeCharacterCount 
        let attributedString = NSMutableAttributedString(string: text)
        attributedString.addAttribute(.kern, value: Constant.deviceCodeCharacterSpacing, range: NSRange(location: 0, length: text.count - 1))
        attributedString.addAttribute(.kern, value: 1, range: NSRange(location: Constant.deviceCodeCharacterCount - 1, length: 1))
        textField.attributedText = attributedString
    

【讨论】:

【参考方案2】:

试试下面的代码:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool 
        if textField.text?.count ?? 0 <= 7
            if textField.text?.count ?? 0 == 7
                DispatchQueue.main.async 
                    textField.resignFirstResponder()
                
            
            return true
        
        textField.resignFirstResponder()
        return false
    

在 viewController 的 viewDidLoad 方法中将 customTextField 的委托设置为 self,并确认 UITextFieldDelegate 协议

【讨论】:

这只是隐藏了键盘,这不是预期的行为。我只是想防止光标在最后一个字符后跳转。用户仍然可以尝试输入更多或删除字符。【参考方案3】:

如果您尝试此代码会发生什么?

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool

    if range.location < 8 
        return true
    
    // return NO to not change text
    return false

【讨论】:

以上是关于最大输入后禁用 UITextField 光标移动的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollView 中的 UItextfield 并用放大镜移动光标

在UITextField中禁用放大镜

如何在不输入的情况下检测 UITextField 光标移动?

如何在UITextView中以编程方式移动光标?

UITextField 禁用光标

禁用 UITextField 中的闪烁光标?