从Swift中的userInfo获取键盘大小
我一直在尝试添加一些代码,以便在键盘出现时向上移动视图,但是,我在尝试将Objective-C示例转换为Swift时遇到了问题。我已经取得了一些进展,但我仍停留在一条特定的路线上 以下是我一直关注的两个教程/问题: 以下是我目前拥有的代码:从Swift中的userInfo获取键盘大小,swift,uikeyboard,Swift,Uikeyboard,我一直在尝试添加一些代码,以便在键盘出现时向上移动视图,但是,我在尝试将Objective-C示例转换为Swift时遇到了问题。我已经取得了一些进展,但我仍停留在一条特定的路线上 以下是我一直关注的两个教程/问题: 以下是我目前拥有的代码: override func viewWillAppear(animated: Bool) { NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWi
override func viewWillAppear(animated: Bool) {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func keyboardWillShow(notification: NSNotification) {
var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))
UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
let frame = self.budgetEntryView.frame
frame.origin.y = frame.origin.y - keyboardSize
self.budgetEntryView.frame = frame
}
func keyboardWillHide(notification: NSNotification) {
//
}
目前,我在这条线上遇到了一个错误:
var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))
如果有人能让我知道这行代码应该是什么,我应该设法自己解决其余的问题。您的代码中有一些问题:
var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))
notification.userInfo返回可选字典[NSObject:AnyObject]?,
因此,在访问其值之前,必须先将其展开。
Objective-C NSDictionary映射到Swift本机词典,因此您必须
使用字典下标语法dict[key]访问这些值。
该值必须强制转换为NSValue,以便可以对其调用CGRectValue。
所有这些都可以通过组合使用可选分配、可选链接和可选强制转换来实现:
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
// ...
} else {
// no UIKeyboardFrameBeginUserInfoKey entry in userInfo
}
} else {
// no userInfo dictionary in notification
}
或者一步到位:
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
// ...
}
if let keyboardSize = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? CGRect {
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
// ...
}
Swift 3.0.1 Xcode 8.1的更新:
或者一步到位:
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
// ...
}
if let keyboardSize = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? CGRect {
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
// ...
}
Swift 5 Xcode 11.6的更新:
我建议使用keyboardFrameEndUserInfoKey而不是keyboardFrameBeginUserInfoKey,因为在较旧的iOS设备上首次显示后,键盘会更改初始渲染高度。您可以使用这一行作为行
var keyboardSize:CGSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue().size
这帮助了我:
对于更少的代码考虑查看
这对我真的很有帮助。 只需在视图控制器中包含视图约束,并使用添加的两个观察者即可。然后只需使用以下方法,这里假设您移动一个tableViewfunc keyboardWillShow(sender: NSNotification) {
if let userInfo = sender.userInfo {
if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().size.height {
tableViewBottomConstraint.constant = keyboardHeight
UIView.animateWithDuration(0.25, animations: { () -> Void in
self.view.layoutIfNeeded()
})
}
}
}
及
如果您使用的是情节提要,而不是操纵视图本身,则可以利用自动布局 这是尼古拉斯答案的一个清晰版本 设置通知中心以通知您键盘的出现和消失:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
}
并确保在不再需要观察员时将其移除:
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: self.view.window)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window)
}
在故事板内部,设置底部约束。创建该约束的出口:
并在显示或隐藏键盘时设置约束的常量属性:
func keyboardWillShow(notification: NSNotification) {
guard let keyboardHeight = (notification.userInfo! as NSDictionary).objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue.size.height else {
return
}
nameOfOutlet.constant = keyboardHeight
view.layoutIfNeeded()
}
func keyboardWillHide(notification: NSNotification) {
nameOfOutlet.constant = 0.0
view.layoutIfNeeded()
}
现在,每当键盘出现或消失时,自动布局将处理所有问题。Swift 2
斯威夫特3
Swift 3:更新
Swift 3.0
下面是一个检索键盘大小并使用它向上设置视图动画的示例。在我的例子中,当用户开始键入时,我会向上移动一个包含UITextFields的UIView,这样他们就可以完成表单,并且仍然可以看到底部的submit按钮
我在要设置动画的视图的底部空间约束中添加了一个插座,并将其命名为myViewsBottomSpaceConstraint:
然后,我将以下代码添加到我的swift类中:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
}
func keyboardWillShow(notification: NSNotification) {
let userInfo = notification.userInfo as! [String: NSObject] as NSDictionary
let keyboardFrame = userInfo.value(forKey: UIKeyboardFrameEndUserInfoKey) as! CGRect
let keyboardHeight = keyboardFrame.height
myViewsBottomSpaceConstraint.constant = keyboardHeight
view.layoutIfNeeded()
}
func keyboardWillHide(notification: NSNotification) {
myViewsBottomSpaceConstraint.constant = 0.0
view.layoutIfNeeded()
}
细节
Xcode版本11.1 11A1027,iOS 13,Swift 5
解决方案
用法
全样本
后果
日志
对于xamarin,您可以使用
c6
c7
在Swift 4.2中,您可以使用UIResponder.keyboardFrameEndUserInfoKey
guard let userInfo=notification.userInfo,let keyboardFrame:CGRect=userInfo[UIResponder.keyboardFrameEndUserInfoKey]as?CGRect else{return}```
Swift-键盘距键盘的高度将显示通知
您可以使用来自键盘的数据将约束或任何其他值增大或缩小到键盘的大小将显示/隐藏通知
具有布局约束
此最小代码注册键盘将显示并基于其大小更新约束的通知
@IBOutlet弱var键盘约束:NSLayoutConstraint!
让键盘约束margin:CGFloat=20
覆盖func viewDidLoad{
super.viewDidLoad
NotificationCenter.default.addObserverforName:UIResponder.keyboardWillShowNotification,对象:nil,队列:nil{中的通知
如果让keyboardSize=notification.userInfo?[UIResponder.KeyboardFrameBeginUserInfo]作为?cRect{
self.keyboardConstraint.constant=keyboardSize.height+self.keyboardConstraintMargin
}
}
NotificationCenter.default.addObserverforName:UIResponder.keyboardDidHideNotification,对象:nil,队列:nil{notification in
self.keyboardConstraint.constant=self.keyboardConstraintMargin
}
}
带滚动视图
同样,这会根据键盘的大小更新滚动视图的内容插入
@iBCROLLVIEW:UIScrollView!
覆盖func viewDidLoad{
super.viewDidLoad
NotificationCenter.default.addObserverforName:UIResponder.keyboardWillShowNotification,对象:nil,队列:nil{中的通知
如果让keyboardSize=notification.userInfo?[UIResponder.KeyboardFrameBeginUserInfo]作为?cRect{
let insets=UIEdgeInsetstop:0,left:0,bottom:keyboardSize.height,right:0
self.scrollView.contentInset=插入
self.scrollView.scrollIndicator
集合=插入
}
}
NotificationCenter.default.addObserverforName:UIResponder.keyboardDidHideNotification,对象:nil,队列:nil{notification in
让insets=UIEdgeInsetstop:0,left:0,bottom:0,right:0
self.scrollView.contentInset=插入
self.scrollView.ScrollIndicationSets=插入
}
}
直到我在其他地方看到这个答案,我才明白tableViewBottomConstraint是通往Xib的出口。很明显,这是一个完美的答案!如果您使用的是自动-layout@JorisvanLiempd是的,我正在使用自动布局。很好,它帮助了你。看起来动画没有动画块是免费的。在这个答案中,它并不遵循键盘曲线和持续时间。@MartinR我很抱歉我在错误的帖子中发表了评论:sorryHi,我试图通过通知获得键盘大小,但我无法让它工作。我在viewDidload中添加了观察者也尝试了ViewWillAspend NSNotificationCenter.defaultCenter.addObserverself,选择器:keyboardWillShow:,名称:UIKeyboardWillShowNotification,对象:nil,但未调用该方法。我在真实的设备和模拟器上试过了。有什么建议吗?非常感谢。一步回答有价值,但应该是CGRectValue@krotov答案的第一部分是Swift 2,第二部分是Swift 3。该属性在这些版本之间被重命名。我认为最好使用UIKeyboardFrameEndUserInfoKey,而不是UIKeyboardFrameBeginUserInfoKey,因为当键盘边框更改为“预测启用”或切换到iOS 9或更高版本的表情键盘时,强制从该字典中打开键盘边框是不安全的。不可能在那里。谢谢,这对我很有帮助!
func keyboardWillShow(notification: NSNotification) {
guard let keyboardHeight = (notification.userInfo! as NSDictionary).objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue.size.height else {
return
}
nameOfOutlet.constant = keyboardHeight
view.layoutIfNeeded()
}
func keyboardWillHide(notification: NSNotification) {
nameOfOutlet.constant = 0.0
view.layoutIfNeeded()
}
func keyboardWasShown(notification:NSNotification) {
guard let info:[NSObject:AnyObject] = notification.userInfo,
let keyboardSize:CGSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size else { return }
let insets:UIEdgeInsets = UIEdgeInsetsMake(self.scrollView.contentInset.top, 0.0, keyboardSize.height, 0.0)
self.scrollView.contentInset = insets
self.scrollView.scrollIndicatorInsets = insets
}
func keyboardWasShown(notification:NSNotification) {
guard let info:[AnyHashable:Any] = notification.userInfo,
let keyboardSize:CGSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size else { return }
let insets:UIEdgeInsets = UIEdgeInsets(top: self.scrollView.contentInset.top, left: 0.0, bottom: keyboardSize.height, right: 0.0)
self.scrollView.contentInset = insets
self.scrollView.scrollIndicatorInsets = insets
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
}
@IBOutlet weak var myViewsBottomSpaceConstraint: NSLayoutConstraint!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
}
func keyboardWillShow(notification: NSNotification) {
let userInfo = notification.userInfo as! [String: NSObject] as NSDictionary
let keyboardFrame = userInfo.value(forKey: UIKeyboardFrameEndUserInfoKey) as! CGRect
let keyboardHeight = keyboardFrame.height
myViewsBottomSpaceConstraint.constant = keyboardHeight
view.layoutIfNeeded()
}
func keyboardWillHide(notification: NSNotification) {
myViewsBottomSpaceConstraint.constant = 0.0
view.layoutIfNeeded()
}
import UIKit
protocol KeyboardNotificationsDelegate: class {
func keyboardWillShow(notification: NSNotification)
func keyboardWillHide(notification: NSNotification)
func keyboardDidShow(notification: NSNotification)
func keyboardDidHide(notification: NSNotification)
}
extension KeyboardNotificationsDelegate {
func keyboardWillShow(notification: NSNotification) {}
func keyboardWillHide(notification: NSNotification) {}
func keyboardDidShow(notification: NSNotification) {}
func keyboardDidHide(notification: NSNotification) {}
}
class KeyboardNotifications {
fileprivate var _isEnabled: Bool
fileprivate var notifications: [KeyboardNotificationsType]
fileprivate weak var delegate: KeyboardNotificationsDelegate?
init(notifications: [KeyboardNotificationsType], delegate: KeyboardNotificationsDelegate) {
_isEnabled = false
self.notifications = notifications
self.delegate = delegate
}
deinit { if isEnabled { isEnabled = false } }
}
// MARK: - enums
extension KeyboardNotifications {
enum KeyboardNotificationsType {
case willShow, willHide, didShow, didHide
var selector: Selector {
switch self {
case .willShow: return #selector(keyboardWillShow(notification:))
case .willHide: return #selector(keyboardWillHide(notification:))
case .didShow: return #selector(keyboardDidShow(notification:))
case .didHide: return #selector(keyboardDidHide(notification:))
}
}
var notificationName: NSNotification.Name {
switch self {
case .willShow: return UIResponder.keyboardWillShowNotification
case .willHide: return UIResponder.keyboardWillHideNotification
case .didShow: return UIResponder.keyboardDidShowNotification
case .didHide: return UIResponder.keyboardDidHideNotification
}
}
}
}
// MARK: - isEnabled
extension KeyboardNotifications {
private func addObserver(type: KeyboardNotificationsType) {
NotificationCenter.default.addObserver(self, selector: type.selector, name: type.notificationName, object: nil)
}
var isEnabled: Bool {
set {
if newValue {
for notificaton in notifications { addObserver(type: notificaton) }
} else {
NotificationCenter.default.removeObserver(self)
}
_isEnabled = newValue
}
get { return _isEnabled }
}
}
// MARK: - Notification functions
extension KeyboardNotifications {
@objc func keyboardWillShow(notification: NSNotification) {
delegate?.keyboardWillShow(notification: notification)
}
@objc func keyboardWillHide(notification: NSNotification) {
delegate?.keyboardWillHide(notification: notification)
}
@objc func keyboardDidShow(notification: NSNotification) {
delegate?.keyboardDidShow(notification: notification)
}
@objc func keyboardDidHide(notification: NSNotification) {
delegate?.keyboardDidHide(notification: notification)
}
}
class ViewController: UIViewController {
private lazy var keyboardNotifications: KeyboardNotifications! = {
return KeyboardNotifications(notifications: [.willShow, .willHide, .didShow, .didHide], delegate: self)
}()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
keyboardNotifications.isEnabled = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
keyboardNotifications.isEnabled = false
}
}
extension ViewController: KeyboardNotificationsDelegate {
// If you don't need this func you can remove it
func keyboardWillShow(notification: NSNotification) {
print("keyboardWillShow")
guard let userInfo = notification.userInfo as? [String: NSObject],
let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
print("keyboardFrame: \(keyboardFrame)")
}
// If you don't need this func you can remove it
func keyboardWillHide(notification: NSNotification) { print("keyboardWillHide") }
// If you don't need this func you can remove it
func keyboardDidShow(notification: NSNotification) { print("keyboardDidShow") }
// If you don't need this func you can remove it
func keyboardDidHide(notification: NSNotification) { print("keyboardDidHide") }
}
import UIKit
class ViewController: UIViewController {
private lazy var keyboardNotifications: KeyboardNotifications! = {
return KeyboardNotifications(notifications: [.willShow, .willHide, .didShow, .didHide], delegate: self)
}()
override func viewDidLoad() {
super.viewDidLoad()
let textField = UITextField(frame: CGRect(x: 40, y: 40, width: 200, height: 30))
textField.borderStyle = .roundedRect
view.addSubview(textField)
let gesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:)))
view.addGestureRecognizer(gesture)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
keyboardNotifications.isEnabled = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
keyboardNotifications.isEnabled = false
}
}
extension ViewController: KeyboardNotificationsDelegate {
// If you don't need this func you can remove it
func keyboardWillShow(notification: NSNotification) {
print("keyboardWillShow")
guard let userInfo = notification.userInfo as? [String: NSObject],
let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
print("keyboardFrame: \(keyboardFrame)")
}
// If you don't need this func you can remove it
func keyboardWillHide(notification: NSNotification) { print("keyboardWillHide") }
// If you don't need this func you can remove it
func keyboardDidShow(notification: NSNotification) { print("keyboardDidShow") }
// If you don't need this func you can remove it
func keyboardDidHide(notification: NSNotification) { print("keyboardDidHide") }
}
private void KeyboardWillChangeFrame(NSNotification notification)
{
var keyboardSize = notification.UserInfo.ValueForKey(UIKeyboard.FrameEndUserInfoKey) as NSValue;
if (keyboardSize != null)
{
var rect= keyboardSize.CGRectValue;
//do your stuff here
}
}
private void KeyboardWillChangeFrame(NSNotification notification)
{
if (!(notification.UserInfo.ValueForKey(UIKeyboard.FrameEndUserInfoKey) is NSValue keyboardSize)) return;
var rect= keyboardSize.CGRectValue;
}