web-dev-qa-db-fra.com

Comment détecter de manière fiable si un clavier externe est connecté sur iOS 9?

Avant iOS 9, la méthode la plus fiable pour déterminer si un clavier externe était connecté consistait à écouter UIKeyboardWillShowNotification et à définir un champ de texte en premier répondant, comme indiqué dans cette question . La notification se déclencherait lors de l'utilisation du clavier virtuel, mais ne se déclencherait pas si vous utilisiez un clavier externe.

Cependant, ce comportement a maintenant changé avec iOS 9. UIKeyboardWillShowNotification est également déclenché lorsqu'un clavier externe est connecté, car la nouvelle barre d'outils de clavier est maintenant affichée.

Il est toujours possible de détecter la hauteur du clavier et de déterminer s’il s’agit de la barre d’outils plus petite ou du clavier virtuel plus grand affiché. Cependant, cette méthode n’est pas fiable car la hauteur du clavier a changé entre les différentes versions bêta et on ne peut pas compter sur elle pour rester la même dans le temps. 

Existe-t-il une méthode plus fiable pouvant être utilisée avec iOS 9?

30
Sarah Elan

Après être revenu à la question initiale, j'ai trouvé une solution qui fonctionne. 

Il semble que lorsque le clavier virtuel standard est affiché, le cadre du clavier est dans les dimensions de l'écran. Toutefois, lorsqu'un clavier physique est connecté et que la barre d'outils du clavier est affichée, le cadre du clavier est situé à l'extérieur de l'écran. Nous pouvons vérifier si le cadre du clavier est hors écran pour déterminer si la barre d'outils du clavier est affichée.

- (void) keyboardWillShow:(NSNotification *)notification
{
    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;

    if ((keyboard.Origin.y + keyboard.size.height) > height) {
        self.hasKeyboard = YES;
    }
}
47
Sarah Elan

Ce code prend en charge iOS 8 et iOS 9, inputAccessoryView, a une constante double protégée pour être prêt pour de nouvelles modifications dans les futures versions d'iOS et pour prendre en charge de nouveaux appareils:

#define gThresholdForHardwareKeyboardToolbar 160.f // it's minimum height of the software keyboard on non-retina iPhone in landscape mode

- (bool)isHardwareKeyboardUsed:(NSNotification*)keyboardNotification {
    NSDictionary* info = [keyboardNotification userInfo];
    CGRect keyboardEndFrame;
    [[info valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
    float height = [[UIScreen mainScreen] bounds].size.height - keyboardEndFrame.Origin.y;
    return height < gThresholdForHardwareKeyboardToolbar;
}

Remarque: un clavier matériel peut être présent mais non utilisé.

4
Dmitry

Solution d'API privée: (devez saisir le fichier d'en-tête privé - utilisez RuntimeViewer).

Fonctionne bien pour les applications d'entreprise, où vous n'avez pas de restrictions AppStore.

#import "UIKit/UIKeyboardImpl.h"

+ (BOOL)isHardwareKeyboardMode
{
   UIKeyboardImpl *kbi = [UIKeyboardImpl sharedInstance];
   BOOL externalKeyboard = kbi.inHardwareKeyboardMode;
   NSLog(@"Using external keyboard? %@", externalKeyboard?@"YES":@"NO");
   return externalKeyboard;
}
2
Simon Tillson

J'utilise une variante de la réponse de Sarah Elan. J'avais des problèmes avec son approche de certains points de vue. Je n'ai jamais vraiment compris ce qui a causé le problème. Mais il existe un autre moyen de déterminer s’il s’agit d’une barre de défilement du clavier externe ios9, plutôt que du clavier complet.

Il n’est probablement pas très compatible avec l’avant car, s’ils changent la taille de la barre d’annulation, cela freine. Mais, le travail a été fait. J'apprécie les critiques car il doit y avoir un meilleur moyen ...

//... somewhere ...
#define HARDWARE_KEYBOARD_SIZE_IOS9 55 
//

+ (BOOL) isExternalKeyboard:(NSNotification*)keyboardNotification {

  NSDictionary* info = [keyboardNotification userInfo];
  CGRect keyboardEndFrame;
  [[info valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
  CGRect keyboardBeginFrame;
  [[info valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardBeginFrame];

  CGFloat diff = keyboardEndFrame.Origin.y - keyboardBeginFrame.Origin.y;
  return fabs(diff) == HARDWARE_KEYBOARD_SIZE_IOS9;
}
2
Mike

Vous pouvez vous abonner à une notification lorsque le périphérique externe est connecté:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceConnected:) name:EAAccessoryDidConnectNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceDisconnected:) name:EAAccessoryDidDisconnectNotification object:nil];
[[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications];

Ou récupérez simplement la liste des périphériques connectés:

EAAccessoryManager* accessoryManager = [EAAccessoryManager sharedAccessoryManager];

if (accessoryManager)
{
    NSArray* connectedAccessories = [accessoryManager connectedAccessories];
    NSLog(@"ConnectedAccessories = %@", connectedAccessories);
}