Ios 如何检测iPad上是否存在外部键盘?

Ios 如何检测iPad上是否存在外部键盘?,ios,ipad,keyboard,Ios,Ipad,Keyboard,是否有方法检测外部(蓝牙或usb)键盘是否连接到iPad?间接且SDK安全的方法是让文本字段成为第一响应者。如果存在外部键盘,则不应发布ui键盘将显示通知本地通知 更新:这在iOS 9之后不再适用,但是您可以使用键盘尺寸来确定是否涉及硬件或软件键盘。有关详细信息,请参阅 您可以收听“GSEventHardwareKeyboardAttached”(kGSEventHardwareKeyboardAvailabilityChangedNotification)Darwin通知,但这是一个私有API

是否有方法检测外部(蓝牙或usb)键盘是否连接到iPad?

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

更新:这在iOS 9之后不再适用,但是您可以使用键盘尺寸来确定是否涉及硬件或软件键盘。有关详细信息,请参阅

您可以收听
“GSEventHardwareKeyboardAttached”
kGSEventHardwareKeyboardAvailabilityChangedNotification
)Darwin通知,但这是一个私有API,因此如果您使用它,您的应用可能会被拒绝。要检查是否存在外部硬件,请使用private
GSEventIsHardwareKeyboardAttached()
函数


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

这还有另一个级别

  • 如果您没有inputAccessoryView,您将不会收到上述解释所指出的通知
  • 但是,如果您已经为文本视图设置了inputAccessoryView,那么当外部kbd存在时,您仍然会收到UIKeyboard通知——逻辑是您需要将视图动画设置到正确的位置,因此需要通知中包含的动画信息
幸运的是,事件中有足够的信息来确定是否会提交kbd,尽管这仍然有点牵扯其中

如果我们检查通知字典,就会看到以下信息:

UIKeyboardFrameBeginUserInfoKey = NSRect: {{0, 1024}, {768, 308}}
UIKeyboardFrameEndUserInfoKey = NSRect: {{0, 980}, {768, 308}}
那是肖像画;如果我们将设备向上向下旋转,我们会得到:

UIKeyboardFrameBeginUserInfoKey = NSRect: {{0, -308}, {768, 308}}
UIKeyboardFrameEndUserInfoKey = NSRect: {{0, -264}, {768, 308}}
同样地,在景观左侧和景观右侧,我们得到不同的起点和终点位置

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

然而,我们有足够的信息来了解发生了什么:

  • kbd从设备物理底部的屏幕外移动到与inputAccessoryView相同的高度(但被其遮挡)
  • 所以在肖像的情况下,它从1024移动到980——我们必须有一个高度为44的inputAccessoryView,这确实是事实
  • 因此,在纵向中,如果末端y+inputAccessoryView高度==屏幕高度,则kbd不可见。你需要处理其他旋转,但这就是想法

  • 即使在UIExtView实例上使用inputAccessoryView,将其设置为具有帧CGRectZero的UIView实例,也可以使用硬件键盘获得键盘通知的传递。

    这是我在
    UIKeyboardWillShowNotification中获取键盘用户信息高度的代码。如果同时使用物理键盘和虚拟键盘,则可以使用

    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;
    
    - (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 
        //  ...
    }
    

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

    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设备处于正常纵向模式且底部有home(主页)按钮时,通知发送的键盘帧始终以硬件坐标表示,原点为屏幕的右上角。方法-convertRect:fromView将坐标从窗口坐标(=硬件)更改为本地视图坐标


    我发现有了蓝牙键盘,你第一次会收到一个UIKeyboardDidShow通知,屏幕会旋转,但之后就没有了。更难区分固定键盘与未固定/拆分键盘和BT键盘。

    基于此线程,我已经组合了两个静态方法,可以轻松地从键盘通知方法调用它们,以便在键盘出现时正确处理大小调整视图(通常是UIScrollView),而不考虑类型(软件与硬件):

    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;
    

    基于@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);
    

    @哲学的答案对我很有用。解决方案在iOS 8上不那么复杂:

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

    由于前面答案中的大多数方法在iOS 8和iOS 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!
    }
    

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

    CGRect keyboardFrame = [[[notification userInfo] objectForKey:@"UIKeyboardFrameEndUserInfoKey"] CGRectValue];
    CGFloat keyboardRelatedViewsHeight = self.view.window.frame.size.height - keyboardFrame.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];
    }
    

    对于在Xamarin.iOS中查找的任何人

               NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, OnKeyboardNotification);
    
    然后添加OnKeyboardNotification方法

     private void OnKeyboardNotification(NSNotification obj)
        {
                var window = UIApplication.SharedApplication.KeyWindow;
                var view = window.RootViewController.View;
    
                String eventName = (UIKeyboardExtensions.HardwareKeyboardConnected(obj, view)) ? "keyboard_hardware" : "keyboard_software";
    
        }
    

    有没有办法在公共电话上做到这一点?让我的应用程序被拒绝有点违背了首先编写它的目的=)我想指出的是,当您有accessoryView集时,总是调用WillShowNotification。因此,如果您试图测试是否显示accessoryView,这将无法正常工作。旧注释,但值得一提的是,在iOS 9上,即使连接了外部键盘,UIKeyboardWillShowNotification也会被触发。这是因为iOS 9在虚拟键盘上引入了一个带有粘贴/撤消/重做操作的工具栏,即使在