Переходы текста UITextField
У меня есть ViewController
с 2 UITextField
элементами: Логин и Пароль. Я установил делегат для этих полей, который включает следующий код:
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField === self.loginField {
self.loginField.resignFirstResponder()
self.passwordField.becomeFirstResponder()
return false
}
return true
}
Эта логика должна переключать пользователя из текстового поля ввода на пароль, когда он нажимает кнопку "Далее" на клавиатуре. Но я застрял с глюком: после
self.passwordField.becomeFirstResponder()
текст в поле входа переместится в верхний левый угол и обратно. И что более странно: этот глюк воспроизводится только в первый раз, тогда вам нужно воссоздать ViewController
, чтобы наблюдать это поведение
Вот видео с глюком http://tinypic.com/player.php?v=6nsemw%3E&s=8#.VgVb3cuqpHx
Я закончил с этим:
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField === self.loginField {
self.loginField.resignFirstResponder()
// Shitty workaround. Hi, Apple!
self.loginField.setNeedsLayout()
self.loginField.layoutIfNeeded()
self.passwordField.becomeFirstResponder()
return false
}
return true
}
Ответы
Ответ 1
Основываясь на некоторых других идеях, размещенных здесь, это решение, которое легко реализовать, работает (для меня) во всех случаях и не имеет никаких побочных эффектов:
- (void)textFieldDidEndEditing:(UITextField *)textField
{
// Workaround for the jumping text bug.
[textField resignFirstResponder];
[textField layoutIfNeeded];
}
Это решение работает и в том случае, если вы программным образом переходите к следующему полю от -textFieldShouldReturn:
или если пользователь просто касается другого ответчика.
Ответ 2
В подклассе UITextField
вы можете сделать следующее:
-(BOOL)resignFirstResponder
{
BOOL resigned = [super resignFirstResponder];
[self layoutIfNeeded];
return resigned;
}
Трюк здесь состоит в том, чтобы вы вызывали layoutIfNeeded
после того, как был вызван resignFirstResponder
.
Выполнение этого способа весьма удобно, потому что вам не нужно вызывать resignFirstResponder
в обратных вызовах делегата, так как это вызывало у меня проблемы внутри UIScrollView
, однако выше не было:)
Ответ 3
Используйте этот код, чтобы избежать перескакивания текста в UITextField.
- (BOOL) textFieldShouldReturn:(UITextField *)textField{
if(textField == self.txtUserName){
[self.txtEmail becomeFirstResponder];
}
else if (textField == self.txtEmail){
[self.txtPassword becomeFirstResponder];
}
else if (textField == self.txtPassword){
[self.txtConfirmPassword becomeFirstResponder];
}
else if (textField == self.txtConfirmPassword){
[self.txtFirstName becomeFirstResponder];
}
else{
[textField resignFirstResponder];
}
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];
[textField layoutIfNeeded];
}
Ответ 4
Я также сталкиваюсь с той же проблемой. Следующий код работает для меня.
func textFieldDidEndEditing(_ textField: UITextField) {
textField.layoutIfNeeded()
}
Ответ 5
func textFieldDidEndEditing(_ textField: UITextField) {
textField.layoutIfNeeded()
}
Ответ 6
Основываясь на том, что я понимаю из этого:
Эта проблема может быть вызвана, когда у вас есть изменения макета, или анимации, обработанные в обратных вызовах для клавиатуры, будут отображаться и скрывать уведомления (обычно в тех случаях, когда требуется, чтобы текстовое поле было нажато, чтобы клавиатура не скрывала его).
Решение: Я столкнулся с этой проблемой, так как я делал layoutIfNeeded каждый раз, когда клавиатура будет отображаться, получив вызов, считая его безопасным, очевидно, его нет, поэтому, когда я делаю чек, чтобы сделать это, только когда есть необходимость в смене кадров, переход остановился.
Ответ 7
Я не передаю делегатам текстовых полей. Вместо этого я создаю IBAction и присоединяю его к событию "Закончено на выход". Сбой также случается с этим методом, но только в iOS 9. Он выглядит как ошибка ОС.
Мои действия выглядят следующим образом:
@IBAction func textFieldAction(sender: UITextField) {
if sender === usernameField {
passwordField.becomeFirstResponder()
}
}
С вышесказанным происходит сбой, но когда я делаю ниже, глюк уходит:
@IBAction func textFieldAction(sender: UITextField) {
if sender === usernameField {
sender.resignFirstResponder()
passwordField.becomeFirstResponder()
}
}
Мне не нужно звонить setNeedsLayout()
.
Ответ 8
Более "общий" вариант заключается в том, чтобы использовать уведомления прямо внутри вашего подкласса UITextField:
- (void)setupJumpingTextWorkaround {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(forceLayout)
name:UITextFieldTextDidEndEditingNotification object:self];
}
- (void)forceLayout {
[self setNeedsLayout];
[self layoutIfNeeded];
}
Не забывайте отписаться