Как переместить курсор в UITextField после установки его значения
Кто-нибудь может мне помочь с этим: мне нужно реализовать UITextField
для ввода номера. Это число всегда должно быть в десятичном формате с 4 знаками, например 12,3456 или 12,3400. Итак, я создал NSNumberFormatter
это помогает мне с десятичными разрядами.
Я устанавливаю UITextField
значение в
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
метод. Я обрабатываю ввод, использую средство форматирования и, наконец, вызываю [textField setText: myFormattedValue];
Это работает нормально, но этот вызов также перемещает курсор в конец моего поля. Это нежелательно. Например, у меня в поле 12,3400, и курсор находится в самом начале, а пользователь вводит номер 1. Значение результата равно 112,3400, но курсор перемещается в конце. Я хочу закончить курсором, когда пользователь ожидает (сразу после недавно добавленного числа 1). Есть несколько тем о настройке курсора в TextView
но это UITextField
, Я тоже пытался поймать selectedTextRange
поля, которое правильно сохраняет положение курсора, но после setText
вызов метода, это автоматически меняет и источник UITextRange
потерян (изменен на текущий). надеюсь, мое объяснение понятно.
Пожалуйста, помогите мне с этим. большое спасибо вам.
РЕДАКТИРОВАТЬ: Наконец, я решил переключить функциональность на изменение формата после всего редактирования и работает достаточно хорошо. Я сделал это, добавив селектор forControlEvents:UIControlEventEditingDidEnd
,
5 ответов
После UITextField.text
свойство изменено, любые предыдущие ссылки на UITextPosition
или же UITextRange
объекты, которые были связаны со старым текстом, будут установлены в ноль после того, как вы установите свойство текста. Вам необходимо сохранить то, каким будет смещение текста после того, как манипуляция будет ПЕРЕД тем, как вы установите свойство текста.
Это сработало для меня (обратите внимание, вам нужно проверить, является ли cursorOffset - (BOOL) textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange) range replacementString:(NSString *) string
{
UITextPosition *beginning = textField.beginningOfDocument;
UITextPosition *start = [textField positionFromPosition:beginning offset:range.location];
UITextPosition *end = [textField positionFromPosition:start offset:range.length];
UITextRange *textRange = [textField textRangeFromPosition:start toPosition:end];
// this will be the new cursor location after insert/paste/typing
NSInteger cursorOffset = [textField offsetFromPosition:beginning toPosition:start] + string.length;
// now apply the text changes that were typed or pasted in to the text field
[textField replaceRange:textRange withText:string];
// now go modify the text in interesting ways doing our post processing of what was typed...
NSMutableString *t = [textField.text mutableCopy];
t = [t upperCaseString];
// ... etc
// now update the text field and reposition the cursor afterwards
textField.text = t;
UITextPosition *newCursorPosition = [textField positionFromPosition:textField.beginningOfDocument offset:cursorOffset];
UITextRange *newSelectedRange = [textField textRangeFromPosition:newCursorPosition toPosition:newCursorPosition];
[textField setSelectedTextRange:newSelectedRange];
return NO;
}
То, что на самом деле работало для меня, было очень просто, просто использовал основной асинхронный диспетчер:
DispatchQueue.main.async(execute: {
textField.selectedTextRange = textField.textRange(from: start, to: end)
})
А вот и быстрая версия:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let beginning = textField.beginningOfDocument
let start = textField.positionFromPosition(beginning, offset:range.location)
let end = textField.positionFromPosition(start!, offset:range.length)
let textRange = textField.textRangeFromPosition(start!, toPosition:end!)
let cursorOffset = textField.offsetFromPosition(beginning, toPosition:start!) + string.characters.count
// just used same text, use whatever you want :)
textField.text = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
let newCursorPosition = textField.positionFromPosition(textField.beginningOfDocument, offset:cursorOffset)
let newSelectedRange = textField.textRangeFromPosition(newCursorPosition!, toPosition:newCursorPosition!)
textField.selectedTextRange = newSelectedRange
return false
}
Вот быстрая 3 версия
extension UITextField {
func setCursor(position: Int) {
let position = self.position(from: beginningOfDocument, offset: position)!
selectedTextRange = textRange(from: position, to: position)
}
}
Реализуйте код, описанный в этом ответе: перемещение курсора в начало UITextField
NSRange beginningRange = NSMakeRange(0, 0);
NSRange currentRange = [textField selectedRange];
if(!NSEqualRanges(beginningRange, currentRange))
{
[textField setSelectedRange:beginningRange];
}
РЕДАКТИРОВАТЬ: Из этого ответа, похоже, вы можете просто использовать этот код с UITextField, если вы используете iOS 5 или выше. В противном случае вам нужно вместо этого использовать UITextView.
Swift X. Для предотвращения перемещения курсора с последней позиции.
func textFieldDidChangeSelection(_ textField: UITextField) {
let point = CGPoint(x: bounds.maxX, y: bounds.height / 2)
if let textPosition = textField.closestPosition(to: point) {
textField.selectedTextRange = textField.textRange(from: textPosition, to: textPosition)
}
}