UITextField text jumps iOS 9

a 夏天 提交于 2019-11-29 09:25:15

Based on your edited question I can see this, when you tap next button on keyboard:

  1. You're calling resignFirstResponder() and then becomeFirstResponder(). This calls keyboardWillHide notification and then keyboardWillShow notification
  2. In keyboardWillHide you have self.view.layoutIfNeeded() which layouts the view (and subviews - textfields) without animation.

Because of this the textfield layout is "fixed" and when you do animation in keyboardWillShow the text in textfield doesn't "jump" anymore, because you did layout in keyboardWillHide.

But when you just tap another textfield, only keyboardWillShow is called, layout is not "fixed" in textfield and when you animate the view, the text does a "jump" animation.

That's why it doesn't jump when you tap next on keyboard but it does jump when you just tap another textfield.

So I would advise to change it to this:

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

Tnx to 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)
            }
        })
    }
}
Timur Bernikovich

I've faced same issue, when I was trying to change first responder. There is a better solution for this issue. Just implement UITextField subclass and used in places, where your text field can be animated (keyboard, first respond switching and so on).

@interface UITextFieldFixed : UITextField

@end

@implementation UITextFieldFixed

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

@end

More info about issue: https://github.com/foundry/UITextFieldBug

Copy and paste for Swift3...

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

Here is simple code you need to write for stop jumping of text. This is work for me.

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

Put this code in your keyboard will show notification, BEFORE you do any animations:

UIView.performWithoutAnimation({
    self.yourTextField1.layoutIfNeeded()
    self.yourTextField2.layoutIfNeeded()
    //etc.
})
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!