如何将底部视图移动到UIKeyboard顶部
您好我正在尝试使视图的底部与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{
}
}
}
您可以通过下面的自动布局解决方案实现它。
首先,你需要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 deinitialized防止保留循环:
deinit {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
谢谢。即使这两种观点有不同的父母,这种工作是否会奏效 –
有什么意见?我真的不知道我明白你想说什么..我的解决方案只创建一个适应键盘的人为锚点..所以不是按照左,右,上,下来布置视图,而是根据left,right,top和keyboardAwareBottomLayoutGuide.topAnchor。换句话说,通常使用自动布局,而不是使用viewController.view.bottomAnchor使用keyboardAwareBottomLayoutGuide.topAnchor。 –
所以无论你想在你的视图中进行约束,你都会按照通常的方式进行操作,只需使用新的布局指南而不是静态view.bottomAnchor –
至1:使用UIKeyboardWillShow和UIKeyboardWillHide代替UIKeyboardWillChangeFrame – Michael
另一个谜团是当按下键盘向下箭头时不会调用UIKeyboardWillHide。 –