How to Detect If an External Keyboard Is Present on an Ipad

How can I detect if an external keyboard is present on an iPad?

An indirect and SDK-safe way is to make a text field a first responder. If the external keyboard is present, the UIKeyboardWillShowNotification local notification shall not be posted.

Update: This is no longer true since iOS 9, however you may use the keyboard dimensions to determine if a hardware or software keyboard is involved. See How to reliably detect if an external keyboard is connected on iOS 9? for details.

You can listen to the "GSEventHardwareKeyboardAttached" (kGSEventHardwareKeyboardAvailabilityChangedNotification) Darwin notification, but this is a private API, so it's possible your app will get rejected if you use this. To check if the external hardware is present, use the private GSEventIsHardwareKeyboardAttached() function.

UIKit listens to this and sets the UIKeyboardImpl.isInHardwareKeyboardMode property accordingly, but again this is private API.

How to reliably detect if an external keyboard is connected on iOS 9?

After going back to the original question, I've found a solution that works.

It seems that when the regular virtual keyboard is displayed the keyboard frame is within the dimensions of the screen. However when a physical keyboard is connected and the keyboard toolbar is displayed, the keyboard frame is located offscreen. We can check if the keyboard frame is offscreen to determine if the keyboard toolbar is showing.

Objective-C

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

Swift

@objc func keyboardWillShow(_ notification: NSNotification) {
guard let userInfo = notification.userInfo else {return}
let keyboardScreenEndFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let keyboard = self.view.convert(keyboardScreenEndFrame, from: self.view.window)
let height = self.view.frame.size.height
if (keyboard.origin.y + keyboard.size.height) > height {
self.hasKeyboard = true
}
}

iPad: Detecting External Keyboard

(This answer was suggested by Sean Heber on the Apple forums)

When you get a UIKeyboardDidShowNotification, instead of using the frame given by UIKeyboardFrameEndUserInfoKey, simply test where the view's accessory view is and use that, instead. All I do is check to see what the frame of the accessory view is and convert it to my own view's coordinate space. Then I can easily use that frame to decide what to do.

Note: When the on-screen keyboard is shown/hidden using the bluetooth keyboard's eject button, it seems that UIKit sends UIKeyboardDidShowNotification again but not a UIKeyboardWillHideNotification. This is also a confusing inconsistency, but the above workaround is still valid as the system will change the frame of the inputAccessoryView when it slides in the on-screen keyboard, so you can still adjust things accordingly.

How to know if external keyboard is active in iOS

Few Functionalities like

  1. Camera
  2. Push Notifications
  3. bluetooth Keyboard

For these, you need to use Real device instead of simulator. I haven't tested bluetooth keyboard functionality in realtime. but i'm pretending it was one of the feature that to be tested on real device.Please Make me correct if i was thinking wrong.

How can I check if hardware keyboard connected or not?

There are 4 notifications that you can register for. Here's an example:

#pragma mark - Lifecycle

- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillDisappear:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidAppear:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidDisappear:) name:UIKeyboardDidHideNotification object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];

[[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - Notifications

- (void)keyboardWillAppear:(NSNotification *)note
{

}

// E.t.c

The good thing about these notifications is that they are only fired if the virtual keyboard is toggled. Therefore you can trigger your view shift using these notifications. When the user connects a hardware keyboard nothing will happen.

How do I know if there's a hardware keyboard?

Input accessory views are shown at the bottom of the screen if there's a hardware keyboard attached (otherwise they're attached to the top of the on-screen keyboard).

Set the accessory view of your input view to an empty UIView of size CGRectZero. You will receive the show / hide notifications for both cases, and be able to determine the available screen size from the metrics in the notification's userinfo dictionary.

UIView *inputAccessoryView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
inputAccessoryView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
textView.inputAccessoryView = inputAccessoryView;



- (void)keyboardWillShow:(NSNotification*)aNotification {
NSLog(@"%@", [aNotification userInfo]);
}

Logged metrics - note the frame in UIKeyboardFrameEndUserInfoKey is off screen

// (NSDictionary *) {
// UIKeyboardAnimationCurveUserInfoKey = 0;
// UIKeyboardAnimationDurationUserInfoKey = "0.25";
// UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {768, 264}}";
// UIKeyboardCenterBeginUserInfoKey = "NSPoint: {384, 891}";
// UIKeyboardCenterEndUserInfoKey = "NSPoint: {384, 1155}";
// UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 758}, {768, 264}}";
// UIKeyboardFrameChangedByUserInteraction = 0;
// UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 1022}, {768, 264}}";
// }

Update - very similar to user721239's answer in the related question.



Related Topics



Leave a reply



Submit