2013-04-19 3 views
0

У меня есть форма с несколькими текстовыми полями в виде прокрутки. Я пытался решить проблему с клавиатурой, скрывающей некоторые текстовые поля, которые я частично сделал. По крайней мере, он работает хорошо, когда я нажимаю на каждое отдельное поле. Я использовал рекомендованный Apple, подход:Переместить представление при переходе из текстового поля в текстовое поле

Я зарегистрировался для получения уведомлений клавиатуры в viewDidLoad:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.window];          
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:self.view.window]; 

Я отслеживания активных текстовых полей:

- (void)textFieldDidBeginEditing:(UITextField *)textField { 
    activeTextField = textField; 
} 

- (void)textFieldDidEndEditing:(UITextField *)textField { 
    activeTextField = nil; 
} 

Я прокрутке вид вверх, когда клавиатура Отображается:

- (void)keyboardWillShow:(NSNotification *)aNotification { 
    // Get the size of the keyboard 
    NSDictionary* info = [aNotification userInfo]; 
    keyboardHeight = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height; 

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardHeight, 0.0); 
    scrollView.contentInset = contentInsets; 
    scrollView.scrollIndicatorInsets = contentInsets; 

    // If active text field is hidden by keyboard, scroll it so it's visible 
    CGRect aRect = self.view.frame; 
    aRect.size.height -= keyboardHeight + 44 + 44; // Compensates for Navbar and text field height 
    if (!CGRectContainsPoint(aRect, activeTextField.frame.origin)) { 
     [scrollView scrollRectToVisible:activeTextField.frame animated:YES]; 
    } 
} 

Затем я просматриваю вид назад по умолчанию, когда t клавиатура скрыта (я не буду вставлять код просто потому, что он отлично работает).

Однако из моих 5 текстовых полей первые 4 имеют кнопку Next на клавиатуре (вместо или Return), в то время как последнее поле имеет Done. Идея состоит в том, что я хочу, чтобы пользователь переходил из одного текстового поля в другое (в одном случае этого достаточно). Таким образом, я реализовал метод делегата UITextField, чтобы справиться с этим, а также:

- (BOOL)textFieldShouldReturn:(UITextField *)textField { 
    if (textField == firstNameTextField) { 
     [lastNameTextField becomeFirstResponder]; 

    } else if (textField == lastNameTextField) { 
     [countryTextField becomeFirstResponder]; 

    } else if (textField == cityTextField) { 
     [zipCodeTextField becomeFirstResponder]; 

    } else if (textField == zipCodeTextField) { 
     [zipCodeTextField resignFirstResponder]; 
    } 
    return NO; 
} 

Среднее текстовое поле выше пропускается, потому что для этого текстового поля я использую другой тип ввода (настраиваемое представление с UIPickerView и бар на вершине с кнопки Далее) - недостающий код в этом методе:

- (IBAction)goToNextTextField:(id)sender { 
    [cityTextField becomeFirstResponder]; 
} 

ОК, как я уже упоминал, регулировка вид хорошо работает при касании отдельных текстовых полей (а затем отклоняя клавиатуры) , хотя размеры клавиатуры (стандартная iOS против моего пользовательского представления) различаются по высоте. Я также могу успешно пройти все текстовые поля, нажимая кнопки «Далее».

Вот мои вопросы, хотя:

  • При нажатии на Next, если клавиатура не меняется (скажем, от поля 4 до 5, что оба используют стандартную клавиатуру), мой keyboardWillShow: метод не вызывается, Отладчик NSLog показывает keyboardHeight как 0, и все же представление перемещается непредсказуемо.
  • Кроме того, при навигации к полю и из поля 3 (тот, который использует пользовательский вид ввода), клавиатураHight не перерасчитывается. Я пробовал зарегистрироваться в UIKeyboardDidChangeFrameNotification и UIKeyboardWillChangeFrameNotification (указывая на метод keyboardWillShow:), но без особого успеха. Стоит отметить, что я вижу в консоли, что keyboardHeight меняется, но обычно он отстает на один шаг, т. Е. KeyboardHeight обновляется, когда я покидаю поле, а не когда он становится FirstResponder.

Возможно, пара опытных глаз запятнает свою ошибку, потому что я разрушали мою пару глаз, которые ищут решения за последние 2 дня ..

Спасибо!

ответ

0

У меня в конце реализовано решение, которое хорошо работает для меня. Это смесь рекомендованного Apple подхода, пара решений, найденных на этих форумах, а также моя.

Прежде всего, зарегистрируйтесь как UITextFieldDelegate на контроллере вида .h.

Затем в viewDidLoad зарегистрироваться для получения уведомлений клавиатуры:

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(keyboardWillShow:) 
              name:UIKeyboardWillShowNotification 
              object:self.view.window]; 
[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(keyboardWillHide:) 
              name:UIKeyboardWillHideNotification 
              object:self.view.window]; 

Не забудьте отменить из них (removeObserver :) в методе viewDidUnload, а также.

Пусть ваше приложение знать, какой текстовое поле в настоящее время активен:

- (void)textFieldDidBeginEditing:(UITextField *)textField { 
    activeTextField = textField; 
} 

- (void)textFieldDidEndEditing:(UITextField *)textField { 
    activeTextField = nil; 
} 

Когда приложение получает уведомление, что клавиатура будет показывать, что вызывает этот метод:

- (void)keyboardWillShow:(NSNotification *)aNotification { 

    keyboardHeight = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; 

    [scrollView setFrame:CGRectMake(scrollView.frame.origin.x, 
            scrollView.frame.origin.y, 
            scrollView.frame.size.width, 
            scrollView.frame.size.height - keyboardHeight)]; 

    [self moveViewWithKeyboard]; 
} 

Все, что я делаю здесь уменьшается размер моего scrollView кадра по размеру клавиатуры. После этого я вызываю свой метод moveViewWithKeyboard:, который сделает активный вид видимым.

Интересно, что для решения проблемы правильной высоты клавиатуры, обнаруженной на один шаг слишком поздно (прочитайте мой первоначальный вопрос выше), мне пришлось изменить аргумент UIKeyboardFrameBeginUserInfoKey в строке определения высоты клавиатуры с аргументом UIKeyboardFrameEndUserInfoKey. Сделав это, клавиатура (или пользовательский вид) обнаруживается при переходе в соответствующее поле, а не при удалении от него.

Конечно, я должен восстановить первоначальный вид кадр, когда клавиатура скрывает (и заметьте, что я до сих пор вызов moveViewWithKeyboard: метод с нулем в качестве аргумента):

- (void)keyboardWillHide:(NSNotification *)aNotification { 

    [scrollView setFrame:CGRectMake(scrollView.frame.origin.x, 
            scrollView.frame.origin.y, 
            scrollView.frame.size.width, 
            scrollView.frame.size.height + keyboardHeight)]; 

    [self moveViewWithKeyboard]; 
} 

Я также добавил, звонки в перемещение, когда скрытие/показ клавиатуры не запускается. Это происходит, когда я перехожу из текстового поля в текстовое поле, которое имеет системную клавиатуру в качестве входных данных, поэтому оно не скрывается и не отображается снова (и никаких уведомлений не выдается, чтобы вызвать методы делегата).

- (BOOL)textFieldShouldReturn:(UITextField *)textField { 

    if (textField == firstNameTextField) { 
     [lastNameTextField becomeFirstResponder]; 
    } else if (textField == lastNameTextField) { 
     [countryTextField becomeFirstResponder]; 
    } else if (textField == cityTextField) { 
     [zipCodeTextField becomeFirstResponder]; 
    } else if (textField == zipCodeTextField) { 
     [zipCodeTextField resignFirstResponder]; 
    } 

    [self moveViewWithKeyboard:nil]; 

    return NO; 
} 

И, наконец, мой метод, чтобы переместить вид:

- (void)moveViewWithKeyboard { 

    if (activeTextField) { 
     [scrollView scrollRectToVisible:activeTextField.frame animated:YES]; 
    } else { 
     [scrollView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES]; 
    } 
} 

Обратите внимание, что при отсутствии текстового поля не передается в качестве аргумента (т.е. не текстовое поле не активен), вид прокручивается в исходное положение.

Надеюсь, это поможет кому-то.

0

https://github.com/simonbs/BSKeyboardControls

этот контроль может показывать панель над клавиатурой при редактировании текстового поля, как этого

enter image description here

================= =========================

-(void)textFieldDidBeginEditing:(UITextField *)textField { 
    if (textField == firstNameTextField) { 
     //move to firstNameTextField 

    } else if (textField == lastNameTextField) { 
     //move to lastNameTextField 

    } else if (textField == cityTextField) { 
     //move to cityTextField 

    } else if (textField == zipCodeTextField) { 
     //move to zipCodeTextField 
    } 
    return NO; 
} 
+0

Привет, адали, спасибо за ссылку. Я тоже рассматривал этот вопрос, но у меня слишком много кнопок для моего вкуса, а Done vs Go - это тоже немного.) Это, однако, не решает мою проблему с удобством перемещения взгляда, когда я прыгаю из одного текстового поля в другое, используя только кнопки клавиатуры – artooras

+0

Я рассмотрел ваш вопрос, и если вы сделали много вещей в - (BOOL) textFieldShouldReturn: (UITextField *) textField, почему бы вам не сделать больше? если клавиатураWillShow не вызывается, вы можете вызывать ее вручную, если keyboardHeight не пересчитывается, вы также можете вычислить ее вручную, вам вообще не нужно использовать уведомление, все вещи могут быть не в textFieldShouldReturn, отметьте тег для каждого текстового поля , то вы узнаете, какое текстовое поле активируется :) – adali

+0

Насколько я понимаю, я могу рассчитать высоту клавиатуры только в методе, который имеет параметр aNotification в качестве параметра, поскольку вы извлекаете userInfo и, следовательно, кадр клавиатуры из этого уведомления – artooras

1

Вы можете использовать делегаты UITextField. Всякий раз, когда пользователь начать редактирование в любом текстовом поле его делегат называется вы можете изменить Scrollview смещения с помощью

- (void)scrollViewToCenterOfScreen:(UIView *)theView 
{ 
    CGFloat viewCenterY = theView.center.y; 
    CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame]; 

    CGFloat availableHeight = applicationFrame.size.height - 200;   // Remove area covered by keyboard 

    CGFloat y = viewCenterY - availableHeight/2.0; 
    if (y < 0) 
    { 
     y = 0; 
    } 
    [scrollView setContentOffset:CGPointMake(0, y+20) animated:YES]; 
} 

Так что в TextField делегате вы можете установить

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField 
{ 
    if([textField isEqual:textfield1]) 
    { 
     [self scrollViewToCenterOfScreen:textfield1]; 

    } 
    else if([textField isEqual:textfield2]) 
    { 
     [self scrollViewToCenterOfScreen:textfield2]; 

    } 

return YES; 
} 

и когда пользователь нажмет сделали или кнопку вы можете изменить смещение возврата до (0,0)

[scrollView setContentOffset:CGPointMake(0, 0) animated:YES]; 

Надеюсь, это сработает для вас.

+0

Спасибо за предложенный подход. Я сохраню его как резервный вариант, если не смогу найти решение для моего первоначального подхода. Центрирование текстового поля может выглядеть немного далеко от клавиатуры на iPhone 5 ... – artooras

+0

Вы можете использовать изменение ContentOffset в соответствии с изменением y в соответствии с вашими потребностями. –