Подтвердить что ты не робот

Как перемещать курсор в 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 теряется (изменяется на текущий). надеюсь, мое объяснение ясно.

Пожалуйста, помогите мне с этим. Большое спасибо.

EDIT: Наконец, я решил переключить функциональность на изменение формата после целого редактирования и работает достаточно хорошо. Я сделал это, добавив селектор forControlEvents:UIControlEventEditingDidEnd.

4b9b3361

Ответ 1

После изменения свойства UITextField.text любые предыдущие ссылки на объекты UITextPosition или UITextRange, которые были связаны со старым текстом, будут установлены равными нулю после того, как вы установите свойство text. Вам нужно сохранить то, что будет смещаться по тексту, после того, как манипуляция будет установлена ​​до того, как вы установите свойство текста.

Это сработало для меня (обратите внимание, что вам нужно проверить, является ли cursorOffset значением < textField.text.length, если вы удаляете любые символы из t в приведенном ниже примере):

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

Ответ 2

И вот быстрая версия:

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

Вот быстрая версия 3

extension UITextField {
    func setCursor(position: Int) {
        let position = self.position(from: beginningOfDocument, offset: position)!
        selectedTextRange = textRange(from: position, to: position)
    }
}

Ответ 4

Внедрите код, описанный в этом ответе: Перемещение курсора в начало UITextField

NSRange beginningRange = NSMakeRange(0, 0);
NSRange currentRange = [textField selectedRange];
if(!NSEqualRanges(beginningRange, currentRange))
{
    [textField setSelectedRange:beginningRange];
}

РЕДАКТИРОВАТЬ: От этот ответ, похоже, вы можете просто использовать этот код с вашим UITextField, если используете iOS 5 или выше. В противном случае вам нужно использовать UITextView.

Ответ 5

Что на самом деле работало для меня, было очень просто, просто использовалась основная асинхронная рассылка:

DispatchQueue.main.async(execute: {
  textField.selectedTextRange = textField.textRange(from: start, to: end)
})

Ответ 6

Свифт Х. Для предотвращения перемещения курсора из последней позиции.

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