2012-06-22 3 views
24

может кто-нибудь мне помочь в этом: мне нужно реализовать UITextField для ввода номера. Это число всегда должно быть в десятичном формате с 4 местами, например. 12.3456 или 12.3400. Итак, я создал NSNumberFormatter, который помогает мне с десятичными знаками.как перемещать курсор в UITextField после установки его значения

Я устанавливаю значение UITextField в

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string метода. I вход proccess, использование форматирования и, наконец, звонок [textField setText: myFormattedValue];

Это прекрасно работает, но этот вызов также перемещает курсор в конец моего поля. Это нежелательно. Например. У меня 12.3400 в моем поле, и курсор находится в самом начале и пользовательских типов номер 1. Значение результата равно 112.3400, но курсор перемещается в конце. Я хочу завершить курсор, когда пользователь ожидает (сразу после добавления номера 1). Есть несколько тем, касающихся установки курсора в TextView, но это UITextField. Я также попытался поймать поле selectedTextRange, которое сохраняет позицию курсора правильно, но после вызова setText это автоматически изменяется, а источник UITextRange теряется (изменен на текущий). надеюсь, мои объяснения понятны.

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

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

+0

Когда вы читаете 'selectedTextRange', вы можете не копировать его как свойство в классе, который действует как' UITextFieldDelegate', а затем повторно установить это после 'setText:'? –

+1

Phillip, это не работает.После того, как вы установили текст с помощью setText, UITextRange, который вы собрали перед установкой текста, сбрасывается в нуль, и поэтому вы не можете повторно применить его к завершенному UITextField. – JasonD

ответ

2

Реализовать код, описанный в этом ответе: Moving the cursor to the beginning of UITextField

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

EDIT: Из this answer, похоже, вы можете просто использовать этот код с UITextField, если вы используете IOS 5 или выше. В противном случае вам нужно использовать UITextView.

38

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

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

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

Работал отлично для меня. Спасибо, JasonD! –

+2

Работает отлично. Спасибо!!! – RohinNZ

+0

tnx очень, я добавил быструю версию ниже для ленивых :) – ergunkocak

3

А вот быстры версия:

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

Вот скор 3 версия

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

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

DispatchQueue.main.async(execute: { 
    textField.selectedTextRange = textField.textRange(from: start, to: end) 
}) 
Смежные вопросы