如何检测iPad上是否有外接键盘?

有没有办法检测一个外部(蓝牙或USB)键盘是否连接到iPad?

间接和SDK安全的方法是使文本字段成为第一响应者。 如果外部键盘存在,则不应发布UIKeyboardWillShowNotification本地通知。

您可以听"GSEventHardwareKeyboardAttached"kGSEventHardwareKeyboardAvailabilityChangedNotification )Darwin通知,但是这是一个私人API,所以如果您使用这个API,您的应用程序可能会被拒绝。 要检查外部硬件是否存在,请使用专用的GSEventIsHardwareKeyboardAttached()函数。

UIKit监听此并相应地设置UIKeyboardImpl.isInHardwareKeyboardMode属性,但是这又是私有API。

还有另一个层面。

  • 如果你没有一个inputAccessoryView,你将不会得到上面的解释指出的通知。
  • 但是,如果您为文本视图设置了一个inputAccessoryView,那么当外部kbd存在时,您仍然会收到一个UIKeyboard通知 – 您需要将视图animation到正确的位置,这样就需要animation通知中包含的信息。

幸运的是,有足够的信息来确定kbd是否会被呈现,尽pipe它仍然有一点涉及。

如果我们检查通知字典,我们看到这个信息:

 UIKeyboardFrameBeginUserInfoKey = NSRect: {{0, 1024}, {768, 308}} UIKeyboardFrameEndUserInfoKey = NSRect: {{0, 980}, {768, 308}} 

这是在肖像; 如果我们将设备旋转到PortraitUpsideDown,我们会得到:

 UIKeyboardFrameBeginUserInfoKey = NSRect: {{0, -308}, {768, 308}} UIKeyboardFrameEndUserInfoKey = NSRect: {{0, -264}, {768, 308}} 

同样在LandscapeLeft和LandscapeRight,我们得到不同的开始和结束位置。

嗯…这些数字是什么意思? 你可以看到kbd是在屏幕外开始的,但是它确实移动了一点点。 更糟糕的是,根据设备的方向,kbd位置是不同的。

但是,我们有足够的信息来弄清楚发生了什么事情:

  1. kbd从设备物理底部的屏外移动到与inputAccessoryView相同的高度(但被其遮挡)
  2. 所以在肖像的情况下,它从1024移动到980 – 我们必须有一个高度为44的inputAccessoryView,的确如此。
  3. 所以在纵向如果结束y + inputAccessoryView height ==屏幕高度,那么kbd是不可见的。 你需要处理其他轮换,但是这是主意。

build立在@ user721239 if条件决定了键盘的底部是否在self.view的框架之外。 “convertRect”规范化框架的任何方向。

 - (void)keyboardWillShow:(NSNotification *)notification { keyboardFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; keyboardFrame = [self.view convertRect:keyboardFrame fromView:nil]; // convert orientation keyboardSize = keyboardFrame.size; //NSLog(@"keyboardFrame.origin.y = %f", keyboardFrame.origin.y); //NSLog(@"keyboardFrame.size.height = %f", keyboardFrame.size.height); BOOL hardwareKeyboardPresent = FALSE;; if ((keyboardFrame.origin.y + keyboardFrame.size.height) > (self.view.frame.size.height+self.navigationController.navigationBar.frame.size.height)) { hardwareKeyboardPresent = TRUE; } //NSLog(@"bottomOfKeyboard = %f", bottomOfKeyboard); //NSLog(@"self.view.frame.size.height = %f", self.view.frame.size.height); 

即使使用您的UITextView实例上的inputAccessoryView设置为具有框架的UIView的实例CGRectZero的工作,以获得与硬件键盘一起工作的键盘通知的交付。

这是我用来从UIKeyboardWillShowNotification获取键盘userInfo的高度的代码。 适用于物理和虚拟键盘。

 NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]; CGRect keyboardRect = [aValue CGRectValue]; CGFloat deviceHeight = [UIScreen mainScreen].bounds.size.height; CGFloat deviceWidth = [UIScreen mainScreen].bounds.size.width; CGFloat newKeyboardHeight; if (interfaceOrientation == UIInterfaceOrientationPortrait) newKeyboardHeight = deviceHeight - keyboardRect.origin.y; else if (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) newKeyboardHeight = keyboardRect.size.height + keyboardRect.origin.y; else if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) newKeyboardHeight = deviceWidth - keyboardRect.origin.x; else newKeyboardHeight = keyboardRect.size.width + keyboardRect.origin.x; 

基于这个线程,我已经组装了两个静态方法,我可以从键盘通知方法轻松调用,以便在出现键盘时处理正确调整视图大小(通常为UIScrollViews),而不pipetypes(软件还是硬件):

 + (void)keyboardWillShowHide:(NSNotification *)notification inView:(UIView *)view adjustView:(UIView *)viewToAdjust { // How much should we adjust the view's frame by? CGFloat yOffset = [SMKeyboardUtil keyboardOffsetForKeyboardNotification:notification inView:view]; CGRect viewFrame = viewToAdjust.frame; viewFrame.size.height -= yOffset; // Get the animation parameters being used to show the keyboard. We'll use the same animation parameters as we // resize our view. UIViewAnimationCurve animationCurve; NSTimeInterval animationDuration; [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve]; [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration]; // Resize the view's frame to subtract/add the height of the keyboard (and any inputAccessoryView) [UIView beginAnimations:@"animate resiz view" context:nil]; [UIView setAnimationDuration:animationDuration]; [UIView setAnimationCurve:animationCurve]; [viewToAdjust setFrame:viewFrame]; [UIView commitAnimations]; } + (CGFloat)keyboardOffsetForKeyboardNotification:(NSNotification *)notification inView:(UIView *)view { NSAssert(notification.userInfo[UIKeyboardFrameBeginUserInfoKey], @"Invalid keyboard notification"); // Get the frame of keyboard from the notification CGRect keyboardFrameBeginRaw = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; CGRect keyboardFrameEndRaw = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; // Because the frame we get from the notification is raw screen coordinates, without accounting for device orientation, // we need to convert the frame to be relative to our view. CGRect keyboardFrameBegin = [view convertRect:keyboardFrameBeginRaw fromView:nil]; CGRect keyboardFrameEnd = [view convertRect:keyboardFrameEndRaw fromView:nil]; // We could examine the size of the frame, but this does not account for hardware keyboards. Instead, // we need to need the delta between the start and end positions to determine how much to modify // the size of our view. return keyboardFrameBegin.origin.y - keyboardFrameEnd.origin.y; } 

当连接硬件键盘时,您可以使用以下内容来计算键盘/工具栏高度的高度。 您将需要订阅KeyboardWillShow通知:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; 

然后像这样处理通知:

 - (void)keyboardWillShow:(NSNotification *)notification { // Information we want to determine from notification BOOL isHardwareKB = NO; CGFloat keyboardHeight; // Notification info NSDictionary* userInfo = [notification userInfo]; CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGRect keyboard = [self.view convertRect:keyboardFrame fromView:self.view.window]; CGFloat height = self.view.frame.size.height; // Determine if hardware keyboard fired this notification if ((keyboard.origin.y + keyboard.size.height) > height) { isHardwareKB = YES; keyboardHeight = height - keyboard.origin.y; // toolbar height } else { isHardwareKB = NO; // As this value can change depending on rotation keyboardHeight = MIN(keyboardFrame.size.width, keyboardFrame.size.height); } // adjust view ui constraints ext ext depending on keyboard height // .... } 

您也可以处理KeyboardWillHide通知。 当硬件和软件键盘的第一个响应者将会被触发。

 - (void)keyboardWillShow:(NSNotification *)notification { // Information we want to determine from notification BOOL isHardwareKB; // this is irrelevant since it is hidden CGFloat keyboardHeight = 0; // height is now 0 // Do any view layout logic here for keyboard height = 0 // ... } 

另外不要忘记删除观察者:

 -(void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [super dealloc]; } 

由于以前答案中的大多数方法已被iOS 8和9弃用,我将键盘报告的框架与当前窗口相交,以获得实际可见的键盘框架。 然后你可以检查高度是否有变化。

 CGRect reportedKeyboardFrameRaw = [[[notification userInfo] valueForKey: UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGRect reportedKeyboardFrame = [self.view.window convertRect: reportedKeyboardFrameRaw fromWindow:nil]; CGRect visibleKeyboardFrame = CGRectIntersection(reportedKeyboardFrame, self.view.window.frame); if (reportedKeyboardFrame.size.height != visibleKeyboardFrame.size.height) { // External keyboard present! } 

以下代码为您提供了所有方向的键盘框架,无论您是使用全屏视图还是使用分割视图的详细视图。

 NSDictionary* info = [aNotification userInfo]; CGRect frame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGRect keyboardEndFrame = [self.view convertRect:frame fromView:nil]; // The raw frame values are physical device coordinate. CGSize keyboardSize = keyboardEndFrame.size; 

当iOS设备处于正常人像模式并且主页button位于底部时,由通知传送的键盘框始终以硬件坐标为原点,作为屏幕的右上angular。 方法-convertRect:fromView将坐标从窗口坐标(=硬件)更改为本地视图坐标。

我发现用蓝牙键盘,第一次有一个屏幕旋转,但没有一个后,你会得到一个UIKeyboardDidShowNotification。 使对接键盘与未连接/分离键盘和BT键盘的区分更加困难。

这不是检测外部键盘是否存在的直接答案,但是我这样做是为了检测在屏幕底部显示键盘相关视图所需的实际高度。

 CGRect keyboardFrame = [[[notification userInfo] objectForKey:@"UIKeyboardFrameEndUserInfoKey"] CGRectValue]; CGFloat keyboardRelatedViewsHeight = self.view.window.frame.size.height - keyboardFrame.origin.y; 

@ philosophistry的答案为我工作。 在iOS 8上解决scheme不那么复杂:

 CGRect keyboardRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGFloat deviceHeight = [UIScreen mainScreen].bounds.size.height; CGFloat keyboardHeight = deviceHeight - keyboardRect.origin.y; NSLog(@"actualKeyboardHeight = %f", keyboardHeight);