2015-10-07 3 views
9

Ссылка на предыдущий вопрос: UITextField text jumpsUITextField текст перескакивает IOS 9

Коротко: У меня есть ViewController с 2 UITextField элементами. Когда loginField является firstResponder, после

self.passwordField.becomeFirstResponder() 

текст в поле логина переходит на левый верхний угол и обратно. И что более странно: этот глюк воспроизводит только первый раз, то вам необходимо заново ViewController наблюдать такое поведение

Вот видео глюка http://tinypic.com/player.php?v=6nsemw%3E&s=8#.VgVb3cuqpHx

я закончил с этим (не работает прошивка 9) :

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 
} 

Есть ли кто-нибудь, кто попал в эту ошибку? Какие-либо предложения?

уведомления клавишные обработчики

Моя главная точка зрения UIScrollView, для которых я меняю нижнее пространство SuperView, так что пользователь может прокручивать все содержимое, даже когда клавиатура отображается

func keyboardWillShow(notification : NSNotification) { 
    let keyboardInfo = notification.userInfo! 
    let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue 
    let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue! 

    UIView.animateWithDuration(animDuration, animations: { 
     self.scrollViewBottom.constant = keyboardFrame.height 
     self.view.layoutIfNeeded() 

     let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height 
     if offsetY > 0 { 
      self.scrollView.contentOffset = CGPointMake(0, offsetY) 
     } 
    }) 
} 

func keyboardWillHide(notification : NSNotification) { 
    self.scrollViewBottom.constant = 0 
    self.view.layoutIfNeeded() 
} 

Как я обнаружил уведомления клавиатуры в iOS7, 8 и 9 очень отличаются. Таким образом, в iOS 9 уведомления отправляются при изменении первогоResponder, даже если клавиатура не будет показывать/скрывать. Кроме того, когда я меняю firstResponder с нажатием на textField (не нажимая Next на клавиатуре, который обрабатывается моим кодом), есть только уведомление KeyboardWillShow и не KeyboardWillHide. И как для меня, USERINFO имеет несколько значений трэша кадров, здесь необходимо войти при смене первого ответчика с помощью следующей кнопки (работает нормально, без глюков):

2015-10-07 12: 54: 13,870 keyboardWillHide: [ UIKeyboardFrameBeginUserInfoKey: NSRect: {{0, 352}, {320, 216}}, UIKeyboardCenterBeginUserInfoKey: NSPoint: {160, 460}, UIKeyboardFrameEndUserInfoKey: NSRect: {{0, 568}, {320, 216}}, UIKeyboardCenterEndUserInfoKey : NSPoint: {160, 676}, UIKeyboardAnimationDurationUserInfoKey: 0.25, UIKeyboardIsLocalUserInfoKey: 1, UIKeyboardBoundsUserInfoKey: NSRect: {{0, 0}, {320, 216}}, UIKeyboardAnimationCurveUserInfoKey: 7] 2015-10-07 12: 54: 13,896 keyboardWillShow: [UIKeyboardFrameBeginUserInfoKey: NSRect: {{0, 352}, {320, 216}}, UIKeyboardCenterBeginUserInfoKey: NSPoint: {160, 460}, UIKeyboardFrameEndUserInfoKey: NSRect : {{0, 352}, {320, 216}}, UIKeyboardCenterEndUserInfoKey: NSPoint: {160, 460}, UIKeyboardAnimationDurationUserInfoKey: 0.25, UIKeyboardIsLocalUserInfoKey: 1, UIKeyboardBoundsUserInfoKey: NSRect: {{0, 0}, {320 , 216}}, UIKeyboardAnimationCurveUserInfoKey: 7]

А вот войти, когда я нажимаю на второй TextField:

2015-10-07 12:55:13.879 keyboardWillShow: [UIKeyboardFrameBeginUserInfoKey: NSRect: {{0, 352}, {320, 216}}, UIKeyboardCenterBeginUserInfoKey: NSPoint: {160, 460}, UIKeyboardFrameEndUserInfoKey: NSRect: {{0, 352}, {320, 216}}, UIKeyboardCenterEndUserInfoKey: NSPoint: {160, 460},
UIKeyboardAnimationDurationUserInfoKey: 0.25, UIKeyboardIsLocalUserInfoKey: 1, UIKeyboardBoundsUserInfoKey: NSRect: {{0, 0}, {320, 216}}, UIKeyboardAnimationCurveUserInfoKey: 7]

Резолюция

Я обнаружил, что у меня есть другой контроллер клавиатуры, который получает уведомления о клавиатуре и делает некоторые анимации. Вот где проблема лежит

+1

Как вы управляете клавиатурой? У вас есть зарегистрированные уведомления о клавиатуре, которые будут отображаться/скрываться? Если да, можете ли вы опубликовать код, что вы там делаете? – haluzak

+0

Tnx для справки, проверьте отредактированный пост – user3237732

+1

Вы получите скроете уведомление, потому что вы вызываете resignFirstResponder() до начала FirstResponder(), «прыжки» вызваны анимацией в клавиатуреWillShow() – haluzak

ответ

7

Основываясь на отредактированном вопрос я могу видеть это, когда вы нажмете следующую кнопку на клавиатуре:

  1. Вы звоните resignFirstResponder(), а затем becomeFirstResponder(). Это вызывает keyboardWillHide уведомление, а затем keyboardWillShow уведомление
  2. В keyboardWillHide у вас есть self.view.layoutIfNeeded(), который отображает представление (и subviews - текстовые поля) без анимации.

Из-за этот макет текстового поля «фиксированный» и когда вы делаете анимацию в keyboardWillShow текст в текстовом поле не «прыгать» больше, потому что вы сделали макет в keyboardWillHide.

Но когда вы просто нажимаете другое текстовое поле, вызывается только keyboardWillShow, макет не «фиксирован» в текстовом поле, и когда вы анимируете представление, текст выполняет «прыгающую» анимацию.

Вот почему он не прыгает, когда вы нажимаете рядом на клавиатуре, но он прыгает, когда вы просто нажимаете другое текстовое поле.

Так что я бы посоветовал изменить его к этому:

func textFieldShouldReturn(textField: UITextField) -> Bool { 
    if textField === self.loginField { 
     self.passwordField.becomeFirstResponder() 
     return false 
    } 

    return true 
} 

func keyboardWillShow(notification : NSNotification) { 
    let keyboardInfo = notification.userInfo! 
    let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue 
    let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue! 

    self.loginField.layoutIfNeeded() 
    self.passwordField.layoutIfNeeded() 

    if keyboardFrame.height != self.scrollViewBottom.constant { 
     UIView.animateWithDuration(animDuration, animations: { 
      self.scrollViewBottom.constant = keyboardFrame.height 
      self.view.layoutIfNeeded() 

      let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height 
      if offsetY > 0 { 
       self.scrollView.contentOffset = CGPointMake(0, offsetY) 
      } 
     }) 
    } 
} 
+0

, к сожалению, это не помогло – user3237732

+0

я даже комментировал мои обработчики уведомлений клавиатуры - глюк по-прежнему сохраняются – user3237732

+0

завернутые как этот UIView.performWithoutAnimation ({ self.loginField.layoutIfNeeded() self.passwordField.layoutIfNeeded() }) и не он работает – user3237732

6

TNX в haluzak:

func textFieldShouldReturn(textField: UITextField) -> Bool { 
    if textField === self.loginField { 
     self.passwordField.becomeFirstResponder() 
     return false 
    } 

    return true 
} 

func keyboardWillShow(notification : NSNotification) { 
    let keyboardInfo = notification.userInfo! 
    let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue 
    let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue! 

    UIView.performWithoutAnimation({ 
     self.loginField.layoutIfNeeded() 
     self.passwordField.layoutIfNeeded() 
    }) 

    if keyboardFrame.height != self.scrollViewBottom.constant { 
     UIView.animateWithDuration(animDuration, animations: { 
      self.scrollViewBottom.constant = keyboardFrame.height 
      self.view.layoutIfNeeded() 

      let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height 
      if offsetY > 0 { 
       self.scrollView.contentOffset = CGPointMake(0, offsetY) 
      } 
     }) 
    } 
} 
+2

Часть 'performWithoutAnimation' была для меня ключом. – teradyl

0

Поместите этот код в клавиатуре будет отображаться уведомление, прежде чем вы сделаете какие-либо анимации:

UIView.performWithoutAnimation({ 
    self.yourTextField1.layoutIfNeeded() 
    self.yourTextField2.layoutIfNeeded() 
    //etc. 
}) 
2

Я столкнулся с той же проблемой, когда пытался изменить первого ответчика. Для этого есть лучшее решение. Просто реализуйте подкласс UITextField и используйте его в местах, где ваше текстовое поле может быть анимировано (клавиатура, первая реакция и т. Д.).

@interface UITextFieldFixed : UITextField 

@end 

@implementation UITextFieldFixed 

- (BOOL)resignFirstResponder 
{ 
    BOOL result = [super resignFirstResponder]; 
    [self setNeedsLayout]; 
    [self layoutIfNeeded]; 
    return result; 
} 

@end 

Более подробную информацию о проблеме: https://github.com/foundry/UITextFieldBug

Копирование и вставка для Swift3 ...

class UITextFieldFixed: UITextField { 
    override func resignFirstResponder() -> Bool { 
     let r = super.resignFirstResponder() 
     self.setNeedsLayout() 
     self.layoutIfNeeded() 
     return r 
    } 
} 
+0

Это фантастический Тимур, спасибо. Я вставил в то же самое в Swift3 - не стесняйтесь редактировать или отменять, Тимур! – Fattie

+0

@JoeBlow спасибо! –

+0

послал награду за отличный ответ здесь – Fattie

0

Вот простой код, который нужно написать для остановки прыжков текста. Это работа для меня.

func textFieldDidEndEditing(_ textField: UITextField) { // Workaround for the jumping text bug. textField.resignFirstResponder() textField.layoutIfNeeded() }

Смежные вопросы