UIKeyboardWillShowNotification is called three times

和自甴很熟 提交于 2019-12-11 11:22:02

问题


I need to move a UIView up as soon as the keyboard will become visible. But the problem I'm facing right now is that my UIKeyboardWillShowNotification is called three times when I'm using a custom Keyboard (e.g. SwiftKey) which results in a bad animation.
Is there a way to handle only the last notification? I could easily dodge the first one because the height is 0, but the second one looks like a valid height and I don't find an answer on how to solve this.
Here is what I've so far:

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillAppear:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillDisappear:", name: UIKeyboardWillHideNotification, object: nil)
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)

    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillAppear(notification: NSNotification){
    print("keyboard appear")
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
        print("with height: \(keyboardSize.height)")
        if keyboardSize.height == 0.0 {
            return
        }
        self.txtViewBottomSpace.constant = keyboardSize.height
        UIView.animateWithDuration(0.4, animations: { () -> Void in
            self.view.layoutIfNeeded()
        })
    }
}

func keyboardWillDisappear(notification: NSNotification){
    print("Keyboard disappear")
    self.txtViewBottomSpace.constant = 0.0
    UIView.animateWithDuration(0.4, animations: { () -> Void in
        self.view.layoutIfNeeded()
    })
}

My Log output is:

keyboard appear
with height: 0.0
keyboard appear
with height: 216.0
keyboard appear
with height: 258.0
Keyboard disappear

So is there any way to only handle the third notification and "ignore" the first two?


回答1:


Set all bellow fields to NO can resolve this problem.

Capitalizaion: None
Correction: No
Smart Dashes: No
Smart insert: No
Smart Quote: No
Spell Checking: No



回答2:


Change the notification name UIKeyboardDidShowNotification and UIKeyboardDidHideNotification then solve the problem

 override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillAppear:", name: UIKeyboardDidShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillDisappear:", name: UIKeyboardDidHideNotification, object: nil)
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)

    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillAppear(notification: NSNotification){
    print("keyboard appear")
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
        print("with height: \(keyboardSize.height)")
        if keyboardSize.height == 0.0 {
            return
        }
        self.txtViewBottomSpace.constant = keyboardSize.height
        UIView.animateWithDuration(0.4, animations: { () -> Void in
            self.view.layoutIfNeeded()
        })
    }
}

func keyboardWillDisappear(notification: NSNotification){
    print("Keyboard disappear")
    self.txtViewBottomSpace.constant = 0.0
    UIView.animateWithDuration(0.4, animations: { () -> Void in
        self.view.layoutIfNeeded()
    })
}



回答3:


I suggest to replace the static animation duration (0.4) with the animation duration of the keyboard, returned in the userInfo dictionary of the notification under UIKeyboardAnimationDurationUserInfoKey. In this way your animation will be in sync with the keyboard animation. You can also retrieve the animation curve used by the keyboard with the UIKeyboardAnimationCurveUserInfoKey key.

func keyboardWillAppear(notification: NSNotification){
    print("keyboard appear")
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
        let animationDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue;
        print("with height: \(keyboardSize.height)")
        if keyboardSize.height == 0.0 {
            return
        }
        self.txtViewBottomSpace.constant = keyboardSize.height
        UIView.animateWithDuration(animationDuration!, delay: 0.0, options: .BeginFromCurrentState, animations: { () -> Void in
            self.view.layoutIfNeeded()
        })
    }
}

func keyboardWillDisappear(notification: NSNotification){
    print("Keyboard disappear")
    let animationDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue;
    self.txtViewBottomSpace.constant = 0.0
        UIView.animateWithDuration(animationDuration!, delay: 0.0, options: .BeginFromCurrentState, animations: { () -> Void in
        self.view.layoutIfNeeded()
    })
}



回答4:


The reason for this is because keyboards can have different sizes, especially third party ones. So the first notification you receive will always be for the default system height, and any you receive after that will include the new heights of a third party keyboard extension if one is loaded. In order to get around this, in your method that handles the notification, you need to get the height originally, and then set that as a default height (I think 226). Then set a variable to this first height, and then for resulting calls to the notification method you can check if the new height is greater than the original height, and if it is you can find the delta, and then readjust your frames accordingly.



来源:https://stackoverflow.com/questions/36033153/uikeyboardwillshownotification-is-called-three-times

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