UITextField text jumps iOS 9

前端 未结 5 1430
名媛妹妹
名媛妹妹 2020-12-19 00:35

Link for previous question: UITextField text jumps

Briefly: I have ViewController with 2 UITextField elements. When loginField is firstResp

相关标签:
5条回答
  • 2020-12-19 00:52

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

    0 讨论(0)
  • 2020-12-19 00:56

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

    UIView.performWithoutAnimation({
        self.yourTextField1.layoutIfNeeded()
        self.yourTextField2.layoutIfNeeded()
        //etc.
    })
    
    0 讨论(0)
  • 2020-12-19 01:00

    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)
                }
            })
        }
    }
    
    0 讨论(0)
  • 2020-12-19 01:03

    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
        }
    }
    
    0 讨论(0)
  • 2020-12-19 01: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)
                }
            })
        }
    }
    
    0 讨论(0)
提交回复
热议问题