如何将底视图移动到UIKeyboard的顶部

嗨,我正在尝试使视图的底部与UIKeyboard的顶部对齐。

更新1:如果您想尝试一下,我已经创建了一个github项目: https : //github.com/JCzz/KeyboardProject

注意:我需要aView是动态的。

更新2:刚推 – 包括使用框架

我可能已经看了太久了,我无法绕过它:-)

你知不知道怎么?

  1. 我如何知道UIKeyboard是否正在向下或向上?

  2. 如果UIKeyboard已启动,那么如何将其与视图对齐(attachKeyboardToFrame – 请参阅代码)。

我找到了以下UIView扩展:

import UIKit extension UIView { func bindToKeyboard(){ NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil) } func unbindFromKeyboard(){ NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil) } @objc func keyboardWillChange(notification: NSNotification) { guard let userInfo = notification.userInfo else { return } let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as! Double let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] as! UInt let curFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue let targetFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue // To get the total height of view let topView = UIApplication.shared.windows.last // let attachKeyboardToFrame = Singleton.sharedInstance.attachKeyboardToFrame let global_attachKeyboardToFrame = self.superview?.convert(attachKeyboardToFrame!, to: topView) if (targetFrame.height + attachKeyboardToFrame!.height) > (topView?.frame.height)! { self.frame.origin.y = -targetFrame.origin.y }else{ } } } 

您可以使用以下Autolayout解决方案来实现它。

首先,您需要UILayoutGuide ,它将用于模拟键盘NSLayoutConstraint底部锚点,以及一个NSLayoutConstraint ,它将控制此布局指南:

 fileprivate let keyboardAwareBottomLayoutGuide: UILayoutGuide = UILayoutGuide() fileprivate var keyboardTopAnchorConstraint: NSLayoutConstraint! 

viewDidLoadkeyboardAwareBottomLayoutGuide添加到视图中并设置相应的约束:

 self.view.addLayoutGuide(self.keyboardAwareBottomLayoutGuide) // this will control keyboardAwareBottomLayoutGuide.topAnchor to be so far from bottom of the bottom as is the height of the presented keyboard self.keyboardTopAnchorConstraint = self.view.layoutMarginsGuide.bottomAnchor.constraint(equalTo: keyboardAwareBottomLayoutGuide.topAnchor, constant: 0) self.keyboardTopAnchorConstraint.isActive = true self.keyboardAwareBottomLayoutGuide.bottomAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor).isActive = true 

然后使用以下行开始收听键盘显示和隐藏:

 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) 

最后,使用以下方法来控制keyboardAwareBottomLayoutGuide来模仿键盘:

 @objc fileprivate func keyboardWillShowNotification(notification: NSNotification) { updateKeyboardAwareBottomLayoutGuide(with: notification, hiding: false) } @objc fileprivate func keyboardWillHideNotification(notification: NSNotification) { updateKeyboardAwareBottomLayoutGuide(with: notification, hiding: true) } fileprivate func updateKeyboardAwareBottomLayoutGuide(with notification: NSNotification, hiding: Bool) { let userInfo = notification.userInfo let animationDuration = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue let keyboardEndFrame = (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue let rawAnimationCurve = (userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uint32Value guard let animDuration = animationDuration, let keybrdEndFrame = keyboardEndFrame, let rawAnimCurve = rawAnimationCurve else { return } let convertedKeyboardEndFrame = view.convert(keybrdEndFrame, from: view.window) let rawAnimCurveAdjusted = UInt(rawAnimCurve << 16) let animationCurve = UIViewAnimationOptions(rawValue: rawAnimCurveAdjusted) // this will move the topAnchor of the keyboardAwareBottomLayoutGuide to height of the keyboard self.keyboardTopAnchorConstraint.constant = hiding ? 0 : convertedKeyboardEndFrame.size.height self.view.setNeedsLayout() UIView.animate(withDuration: animDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: { self.view.layoutIfNeeded() }, completion: { success in // }) } 

现在设置了所有这些,您可以使用Autolayout将您的视图约束到keyboardAwareBottomLayoutGuide.topAnchor而不是self.view.layoutMarginsGuide.bottomAnchor (或self.view.bottomAnchor ,无论您使用哪个)。 keyboardAwareBottomLayoutGuide会自动调整显示或隐藏的键盘。

例:

 uiTextField.bottomAnchor.constraint(equalTo: keyboardAwareBottomLayoutGuide.topAnchor).isActive = true 

编辑:直接设置框架

虽然我强烈建议使用Autolayout,但如果你不能使用它,直接设置框架也可以解决问题。 您可以使用相同的原则。 在这种方法中,您不需要布局指南,因此您不需要任何其他实例属性。 只需使用viewDidLoad注册监听通知:

 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) 

然后实现将对这些通知做出反应的方法:

 @objc fileprivate func keyboardWillShowNotification(notification: NSNotification) { adjustToKeyboard(with: notification, hiding: false) } @objc fileprivate func keyboardWillHideNotification(notification: NSNotification) { adjustToKeyboard(with: notification, hiding: true) } fileprivate func adjustToKeyboard(with notification: NSNotification, hiding: Bool) { let userInfo = notification.userInfo let animationDuration = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue let keyboardEndFrame = (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue let rawAnimationCurve = (userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uint32Value guard let animDuration = animationDuration, let keybrdEndFrame = keyboardEndFrame, let rawAnimCurve = rawAnimationCurve else { return } let convertedKeyboardEndFrame = view.convert(keybrdEndFrame, from: view.window) let rawAnimCurveAdjusted = UInt(rawAnimCurve << 16) let animationCurve = UIViewAnimationOptions(rawValue: rawAnimCurveAdjusted) // we will go either up or down depending on whether the keyboard is being hidden or shown let diffInHeight = hiding ? convertedKeyboardEndFrame.size.height : -convertedKeyboardEndFrame.size.height UIView.animate(withDuration: animDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: { // this will move the frame of the aView according to the diffInHeight calculated above // of course here you need to set all the frames that would be affected by the keyboard (this is why I prefer using autolayout) self.aView?.frame = (self.aView?.frame.offsetBy(dx: 0, dy: diff))! // of course, you can do anything more complex than just moving the aView up.. }) } 

在这两种情况下,一旦取消初始化viewController以防止保留周期,请不要忘记取消注册观察通知:

 deinit { NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) }