在iOS8中无法获得正确的键盘高度值
我正在使用这段代码来确定键盘的大小:
- (void)keyboardWillChange:(NSNotification *)notification { NSDictionary* keyboardInfo = [notification userInfo]; NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey]; CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue]; }
我正在模拟器中运行。
问题是,因为iOS 8这不会给出正确的价值,如果键盘的build议起来,或者如果我把它们推下来,我得到不同的(不正确的)值。
我怎样才能得到键盘的确切大小,包括键盘的build议?
使用
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
随着在iOS中引入自定义键盘,这个问题变得更加复杂。
简而言之, UIKeyboardWillShowNotification可以通过自定义键盘实现多次调用:
- 当Apple系统键盘打开时(纵向)
- UIKeyboardWillShowNotification将以224的键盘高度发送
- Swype键盘打开时(纵向):
- UIKeyboardWillShowNotification以键盘高度0发送
- 用键盘高度216发送UIKeyboardWillShowNotification
- UIKeyboardWillShowNotification以256的键盘高度发送
- 当SwiftKey键盘打开时(纵向):
- UIKeyboardWillShowNotification以键盘高度0发送
- 用键盘高度216发送UIKeyboardWillShowNotification
- UIKeyboardWillShowNotification将以259的键盘高度发送
为了在一个代码行中正确处理这些场景,您需要:
向UIKeyboardWillShowNotification和UIKeyboardWillHideNotification通知注册观察者:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
创build一个全局variables来跟踪当前的键盘高度:
CGFloat _currentKeyboardHeight = 0.0f;
实现keyboardWillShow对当前键盘高度的变化做出反应:
- (void)keyboardWillShow:(NSNotification*)notification { NSDictionary *info = [notification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; CGFloat deltaHeight = kbSize.height - _currentKeyboardHeight; // Write code to adjust views accordingly using deltaHeight _currentKeyboardHeight = kbSize.height; }
注:您可能希望animation的意见偏移。 info字典包含由UIKeyboardAnimationDurationUserInfoKey键入的值。 此值可用于以与显示的键盘相同的速度animation您的更改。
将keyboardWillHide实现为reset _currentKeyboardHeight,并对被解散的键盘做出反应:
- (void)keyboardWillHide:(NSNotification*)notification { NSDictionary *info = [notification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; // Write code to adjust views accordingly using kbSize.height _currentKeyboardHeight = 0.0f; }
我也有这个问题,直到我遇到这个StackOverflow文章:
转换UIKeyboardFrameEndUserInfoKey
这将向您展示如何使用convertRect
函数将键盘的大小转换为可用的值,但在屏幕方向上。
NSDictionary* d = [notification userInfo]; CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue]; r = [myView convertRect:r fromView:nil];
以前,我有一个使用UIKeyboardFrameEndUserInfoKey
的iPad应用程序,但没有使用convertRect
,它工作正常。
但是对于iOS 8,它不能正常工作。 突然,它会报告说,我的键盘,运行在横向模式的iPad,是1024像素高 。
所以现在,在iOS 8中,使用这个convertRect
函数是非常重要的。
类似于用Swift 2.0编写的dangsta的解决scheme:
override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil) } deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } func keyboardWillShow(notification: NSNotification) { guard let kbSizeValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return } guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return } animateToKeyboardHeight(kbSizeValue.CGRectValue().height, duration: kbDurationNumber.doubleValue) } func keyboardWillHide(notification: NSNotification) { guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return } animateToKeyboardHeight(0, duration: kbDurationNumber.doubleValue) } func animateToKeyboardHeight(kbHeight: CGFloat, duration: Double) { // your custom code here }
我对UIViewController
进行了extension
extension UIViewController { func keyboardWillChangeFrameNotification(notification: NSNotification, scrollBottomConstant: NSLayoutConstraint) { let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber let keyboardBeginFrame = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue() let keyboardEndFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue() let screenHeight = UIScreen.mainScreen().bounds.height let isBeginOrEnd = keyboardBeginFrame.origin.y == screenHeight || keyboardEndFrame.origin.y == screenHeight let heightOffset = keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y - (isBeginOrEnd ? bottomLayoutGuide.length : 0) UIView.animateWithDuration(duration.doubleValue, delay: 0, options: UIViewAnimationOptions(rawValue: UInt(curve.integerValue << 16)), animations: { () in scrollBottomConstant.constant = scrollBottomConstant.constant + heightOffset self.view.layoutIfNeeded() }, completion: nil ) } }
你可以这样使用:
override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChangeFrameNotification:", name: UIKeyboardWillChangeFrameNotification, object: nil) } ... deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } func keyboardWillChangeFrameNotification(notification: NSNotification) { self.keyboardWillChangeFrameNotification(notification, scrollBottomConstant: inputContainerBottom) // Write more to here if you want. }
有些时候,开发人员在实际显示之前需要知道键盘高度,以便适当地预先布置界面。
如果是这样的话,这里是一个包容的规格:
这包括在顶部的快速types栏,因为默认情况下在所有当前版本的iOS中。
这里是我用来testing这个的swift 3通知设置,如果有人需要的话:
override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil) } func keyboardWillShow(notification: NSNotification) { guard let keyboardSize = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return } print("\(keyboardSize)") }
我注意到在默认键盘和自定义( UIPickerView
)键盘之间切换时显示的问题 – 在从默认键盘切换之后,自定义键盘将显示253高度而不是162。
在这种情况下工作是设置autocorrectionType = UITextAutocorrectionTypeNo;
用于自定义键盘的input字段。
这个问题只发生在iOS 8(仅在模拟器上testing)。 它不会发生在iOS 9(模拟器或设备)。
只有一个string为快速:
let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size
UIKeyboardFrameEndUserInfoKey
总是存储NSValue
,所以不需要检查。
在Swift中,不在一行中
self.keyboardDidShowObserver = NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: { (notification) in if let userInfo = notification.userInfo, let keyboardFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue { let keyboardRect = keyboardFrameValue.CGRectValue() // keyboardRect.height gives the height of the keyboard // your additional code here... } })
[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) { float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; }];