Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPad split-keyboard

I am creating an app similar to the iPad's iMessage app that does messaging. So there is an input view anchored at the bottom of the message view and input accessory view when the keyboard is shown. Also the message view must be resized properly when the keyboard is shown while docked or undocked.

The problem I have is that the notification data that comes in from UIKeyboardWillChangeFrameNotification is not consistent.

First, there are 3 ways that the user can undock the keyboard:

  1. Press-and-hold the lower right key, then slide up
  2. Press-and-hold the lower right key, when the menu pops up, select "undock"
  3. Press-and-hold the lower right key, when the menu pops up, select "split"

For case #1, the notification data from UIKeyboardWillChangeFrameNotification is consistent. Here is the data:

userInfo = {
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
}

For case #2 and #3 the data is inconsistent, here is what I receive:

userInfo = {
    UIKeyboardAnimationCurveUserInfoKey = 0;
    UIKeyboardAnimationDurationUserInfoKey = "0.25";
    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {384, 872}";
    UIKeyboardCenterEndUserInfoKey = "NSPoint: {384, 1136}";
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
    UIKeyboardFrameChangedByUserInteraction = 0;
    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, -264}, {768, 304}}";
}

What is odd here is that when I listen for UIKeyboardDidChangeFrameNotification under case #2 or #3, the data comes in as expected:

userInfo = {
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
}

Why is the notification data different? Did anybody find a clear way to detect the split-keyboard events?

like image 487
Takeshi Kaga Avatar asked May 25 '12 06:05

Takeshi Kaga


2 Answers

No clear method haven't.

i resolve this trouble in next steps:

  1. Get current orientation.
  2. If orientation is Landscape then i get height of UIKeyboardFrameEndUserInfoKey. it must equals to 216. It means keyboard is Split mode, Else not;
  3. If orientation is Portrait then i get height of UIKeyboardFrameEndUserInfoKey. it must equals to 216. It means keyboard is Split mode, Else not;

I update my gist for example. With convertRect method.

like image 142
Bimawa Avatar answered Oct 20 '22 18:10

Bimawa


This is a somewhat hacky, but reliable way to determine whether the keyboard is split.

NSArray *classPath = @[
  @"KeyboardAutomatic",
  @"KeyboardImpl",
  @"KeyboardLayoutStar",
  @"KBKeyplaneView",
  @"KBSplitImageView"
];
UIView *splitView = textField.inputAccessoryView.superview;
for (NSString *className in classPath) {
  for (UIView *subview in splitView.subviews) {
    if ([NSStringFromClass([subview class]) rangeOfString:className].location != NSNotFound) {
      splitView = subview;
      break;
    }
  }
}
BOOL isSplit = [splitView.subviews count] > 1;

Obviously in order for this to work you need a UITextField/UITextView with a non-nil inputAccessoryView (you can just use an empty view for that).

Note: The behavior of textField.inputAccessoryView.superview is quite finicky, and usually depends on the keyboard having been displayed once before calling superview. Also to pass the App Store submission process I removed the 'UI' prefix from the private class names. That's not a guarantee Apple will not flag your app, but this approach has been used successfully before.

I've only tested it on iOS7 but if it doesn't work on other versions of iOS similar approaches could be used.

like image 36
cagey Avatar answered Oct 20 '22 19:10

cagey