View aligned to top of keyboard appears in wrong p

2019-02-15 04:30发布

iOS 9 adds a Shortcut Bar to the iOS 8 QuickType bar.

As part of this change, if you connect a bluetooth keyboard to an iPad, the keyboard is in a minimized Shortcut Bar only mode (which can be simulated by pressing command-k in the simulator).

I have code which gets the keyboard height using a method similar to the following:

CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat keyboardHeight = keyboardFrame.size.height; // = 313

The problem is that when the keyboard is toggled between the expanded and collapsed state, the height remains the same, causing my view to appear in its old location:

Desired behavior:

enter image description here
(Notice how the red view is attached to the top of the keyboard)

Actual behavior:

enter image description here

What's the correct way to get the red view to be attached to the top of the keyboard?

1条回答
叛逆
2楼-- · 2019-02-15 05:02

The problem is that most code out there (including Apple's) ignores the fact that UIKeyboardFrameEndUserInfoKey is a CGRect and not a CGSize.

// ❌ Bad code, do not use
- (void)keyboardWasShown:(NSNotification*)aNotification {
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect bkgndRect = activeField.superview.frame;
    bkgndRect.size.height += kbSize.height;
    [activeField.superview setFrame:bkgndRect];
    [scrollView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height) animated:YES];
}

Here you see that only the keyboard height (kbSize.height) is being used. The origin of the rect is important, and should not be ignored.

When the keyboard is visible, this is the rect that is reported:

enter image description here

When the keyboard is in Shortcut Bar only mode, this is the rect:

enter image description here

Notice how the majority of the keyboard is offscreen, yet it is still the same height.

To get the correct behavior, use CGRectIntersection with the view's bounds and the keyboard frame within that view:

// ✅ Good code, use
CGRect keyboardScreenEndFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardViewEndFrame = [self.view convertRect:keyboardScreenEndFrame fromView:self.view.window];
CGRect keyboardFrame = CGRectIntersection(self.view.bounds, keyboardViewEndFrame);
CGFloat keyboardHeight = keyboardFrame.size.height; // = 55

For this same reason, UIKeyboardFrameEndUserInfoKey should be used as opposed to UIKeyboardFrameBeginUserInfoKey.

查看更多
登录 后发表回答