When a user taps a UITextField, the keyboard will come up. I scroll up the UITextField to sit just above the keyboard. This is working fine on iPhone:
- (void) someWhere
{
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onKeyboardShow:)
name:UIKeyboardWillShowNotification
object:nil];
}
- (void) onKeyboardShow:(NSNotification *)notification
{
CGRect keyboardRect = [[[notification userInfo]
objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue
];
if (keyboardRect.size.height >= IPAD_KEYBOARD_PORTRAIT_HEIGHT) {
self.containerView.y = self.containerView.y - keyboardRect.size.width;
} else {
self.containerView.y = self.containerView.y - keyboardRect.size.height;
}
}
However, it is broken on iPad. On iPad, modal view controllers can be presented as a sheet that takes up only a portion of the screen. You can see that there is a gap between the last UITextField and the keyboard on iPad.
UINavigationController* nav = [[UINavigationController alloc]
initWithRootViewController:someRootViewController];
nav.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:nav animated:YES completion:nil];
I need to detect the offset of the modal view from the bottom of the screen and add that to the Y coordinate of the UITextField. This will make the UITextField flush with the top of the keyboard. Through some reverse engineering, I got the frame of the modal view by traversing undocumented view hierarchy:
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// describe is a category function on UIView that prints out the frame
[self.viewController.view.superview.superview.superview.superview describe];
}
x: 114.000000,
y: 192.000000,
w: 540.000000,
h: 620.000000
Finally, to get the offset of the modal view from the bottom of the screen, I do:
UIView* modalView = self.viewController.view.superview.superview.superview.superview;
// usage of self-explanatory UIView category methods
CGFloat bottomOffset = modalView.superview.height - (modalView.y + modalView.height);
To my chagrin, this only works in portrait mode. For some reason, the modal view's superview is always stuck with a width of 768 and height of 1024 no matter what orientation the iPad is in. So here is where I'm asking for help. How do I reliably get the offset of the modal view from the bottom of the screen, irregardless of the orientation, on iPad?
I see two possible solutions:
Use an inputAccessoryView
to attach the text field to the keyboard automatically.
Convert the keyboard rect to the superview of the containerView you're trying to move. You can then get its top Y value in the coordinates of the containerView's superview.
Something like:
CGRect rectInWindowCoordinates = [self.containerView.window convertRect:keyboardRect fromWindow:nil];
CGRect rectCoveredByKeyboard = [self.containerView.superview convertRect:rectInWindowCoordinates fromView:nil];
CGFloat top = CGRectGetMinY(rectCoveredByKeyboard);
self.containerView.y = top - self.containerView.frame.size.height;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With