嗨,我正在尝试使视图的底部与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{
}
}
}
最佳答案
您可以使用以下自动布局解决方案来实现。
首先,您需要UILayoutGuide
用于模拟键盘感知的底部锚点,以及一个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
//
})
}
现在,完成所有这些设置后,您可以使用“自动布局”将视图限制为
keyboardAwareBottomLayoutGuide.topAnchor
而不是self.view.layoutMarginsGuide.bottomAnchor
(或self.view.bottomAnchor
,以您所使用的为准)。 keyboardAwareBottomLayoutGuide
将自动调整为显示或隐藏的键盘。例:
uiTextField.bottomAnchor.constraint(equalTo: keyboardAwareBottomLayoutGuide.topAnchor).isActive = true
编辑:直接设置框架
虽然我强烈建议您使用自动版式,但在无法使用自动版式的情况下,直接设置框架也是一种解决方案。您可以使用相同的原理。在这种方法中,您不需要布局指南,因此不需要任何其他实例属性。只需使用
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)
}
关于ios - 如何将底 View 移到UIKeyboard的顶部,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46235188/