如何将底视图移到UIKeyboard的顶部 [英] How to move bottom view to top of UIKeyboard
问题描述
我正在尝试使视图的底部与UIKeyboard的顶部对齐.
Hi I am trying to make a view's bottom align with the top of UIKeyboard.
更新1:如果您想尝试一下,我已经创建了一个github项目: https://github.com/JCzz/KeyboardProject
Update 1: I have created a github project if you would like to give it a try: https://github.com/JCzz/KeyboardProject
注意:我需要aView是动态的.
Note: I need the aView to be dynamic.
更新2:刚刚按下-包括使用框架
Update 2: Just pushed - to include using frames
我可能已经看了太久了,我无法绕开它:-)
I might have been looking at this for too long, I can not wrap my brain around it :-)
你知道吗?
-
我如何知道UIKeyboard是在向下还是向上?
How do I know if the UIKeyboard is on the way down or up?
如果UIKeyboard处于打开状态,则如何将其与视图对齐(attachKeyboardToFrame-请参见代码).
If UIKeyboard is up, then how to align it with the view(attachKeyboardToFrame - see code).
我找到了以下UIView扩展名:
I have found the following UIView extension:
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{
}
}
}
推荐答案
您可以使用以下自动布局解决方案来实现.
You can achieve it using following Autolayout solution.
首先,您需要使用UILayoutGuide
来模拟可识别键盘的底部锚点,并使用NSLayoutConstraint
来控制此布局指南:
First you need UILayoutGuide
that will be used simulate Keyboard aware bottom anchor, and a NSLayoutConstraint
that will control this layout guide:
fileprivate let keyboardAwareBottomLayoutGuide: UILayoutGuide = UILayoutGuide()
fileprivate var keyboardTopAnchorConstraint: NSLayoutConstraint!
在viewDidLoad
中,将keyboardAwareBottomLayoutGuide
添加到视图中并设置适当的约束:
In the viewDidLoad
add the keyboardAwareBottomLayoutGuide
to the view and setup the appropriate contraints:
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
然后使用以下几行开始收听键盘的显示和隐藏操作:
Then use following lines to start listening to keyboard showing and hiding:
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
以模仿键盘:
And finally, use following methods to control the keyboardAwareBottomLayoutGuide
to mimic the keyboard:
@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
将自动调整为显示或隐藏的键盘.
Now with all this set up, you can use Autolayout to constraint your views to keyboardAwareBottomLayoutGuide.topAnchor
instead of self.view.layoutMarginsGuide.bottomAnchor
(or self.view.bottomAnchor
, whichever you use). keyboardAwareBottomLayoutGuide
will automatically adjust to the keyboard showed or hidden.
示例:
uiTextField.bottomAnchor.constraint(equalTo: keyboardAwareBottomLayoutGuide.topAnchor).isActive = true
直接设置框架
虽然我强烈建议您使用自动版式,但如果无法使用自动版式,则直接设置框架也是一种解决方案.您可以使用相同的原理.在这种方法中,您不需要布局指南,因此不需要任何其他实例属性.只需使用viewDidLoad
注册收听通知即可:
While I strongly recommend using Autolayout, in cases when you cannot go with this, directly setting frames can be also a solution. You can use the same principle. In this approach you don't need layout guide, so you don't need any additional instance properties. Just use viewDidLoad
to register for listening notifications:
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)
然后实现将对这些通知做出反应的方法:
Then implement methods that will react to these notifications:
@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进行了初始化以防止保留周期,请不要忘记注销对通知的观察:
In both cases, don't forget to unregister observing the notifications once the viewController is deinitialized to prevent retain cycles:
deinit {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
这篇关于如何将底视图移到UIKeyboard的顶部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!