最大输入后禁用 UITextField 光标移动
Disable UITextField cursor movement after max input
我为固定大小的输入创建了自定义 UITextField 组件。 TextField 的宽度、字体大小、字距调整和字符数都是固定的。我可以阻止用户输入超过 8 个字符(见下面的 shouldChangeCharactersIn 方法),但是在第 8 个字符之后,光标自动移动到下一个位置,这会产生以下问题。
我想显示所有输入的字符而不减小它们的大小。所以
[ 1 2 3 4 5 6 7 8 ]
should be shown instead of
[ 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
}
如果您尝试此代码会发生什么?
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
}
试试下面的代码:
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 的委托设置为自己,并确认 UITextFieldDelegate
协议
我通过更改最后一个字符后的紧排解决了这个问题。所以现在,光标不再跳跃 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
}
}
我为固定大小的输入创建了自定义 UITextField 组件。 TextField 的宽度、字体大小、字距调整和字符数都是固定的。我可以阻止用户输入超过 8 个字符(见下面的 shouldChangeCharactersIn 方法),但是在第 8 个字符之后,光标自动移动到下一个位置,这会产生以下问题。
我想显示所有输入的字符而不减小它们的大小。所以
[ 1 2 3 4 5 6 7 8 ] should be shown instead of [ 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
}
如果您尝试此代码会发生什么?
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
}
试试下面的代码:
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 的委托设置为自己,并确认 UITextFieldDelegate
协议
我通过更改最后一个字符后的紧排解决了这个问题。所以现在,光标不再跳跃 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
}
}