如何将底视图移动到UIKeyboard的顶部
嗨,我正在尝试使视图的底部与UIKeyboard的顶部对齐。
更新1:如果您想尝试一下,我已经创建了一个github项目: https : //github.com/JCzz/KeyboardProject
注意:我需要aView是动态的。
更新2:刚推 – 包括使用框架
我可能已经看了太久了,我无法绕过它:-)
你知不知道怎么?
-
我如何知道UIKeyboard是否正在向下或向上?
-
如果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!
在viewDidLoad
将keyboardAwareBottomLayoutGuide
添加到视图中并设置相应的约束:
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) }