6

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:

enter image description here

- (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.

enter image description here

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?

4

2 回答 2

1

我看到两种可能的解决方案:

  1. 使用 aninputAccessoryView自动将文本字段附加到键盘。

  2. 将键盘矩形转换为您尝试移动的 containerView 的超级视图。然后,您可以在 containerView 的 superview 的坐标中获取其顶部 Y 值。

就像是:

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;
于 2013-09-13T01:52:56.867 回答
0
- (void) onKeyboardShow:(NSNotification *)notification
{
    CGRect keyboardRect = [[[notification userInfo] 
        objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue
    ];    

    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;

    // The keyboard height is only correct when in portrait mode. To get the
    // real height, we make the assumption that keyboards are always wider than
    // they are tall.
    CGFloat keyboardHeight;
    if (keyboardRect.size.width < keyboardRect.size.height) {
        keyboardHeight = keyboardRect.size.width;
    } else {
        keyboardHeight = keyboardRect.size.height;
    }

    CGPoint originOfKeyboardInWindowContext;

    switch (orientation) {
        //
        // (0,0) ___________
        //      |           |
        //      |           |
        //      |           |
        //      |           |
        //      |           |
        //      |===========|
        //      |===========|
        //
        case UIInterfaceOrientationPortrait:
            originOfKeyboardInWindowContext = CGPointMake(0.0, [VeetleAppDelegate instance].window.height - keyboardHeight);
            break;
        //
        //       ___________
        //      |           |
        //      |           |
        //      |           |
        //      |           |
        //      |           |
        //      |===========|
        //      |===========| (0,0)
        //
        case UIInterfaceOrientationPortraitUpsideDown:
            originOfKeyboardInWindowContext = CGPointMake(0.0, keyboardHeight);
            break;
        //
        //       _________________
        //      |                 |
        //      |                 |
        //      |                 |
        //      |=================|
        //      |=================|
        // (0,0)
        //
        case UIInterfaceOrientationLandscapeRight:
            originOfKeyboardInWindowContext = CGPointMake(keyboardHeight, 0.0);
            break;
        //
        //       _________________  (0,0)
        //      |                 |
        //      |                 |
        //      |                 |
        //      |=================|
        //      |=================|
        //
        case UIInterfaceOrientationLandscapeLeft:
            originOfKeyboardInWindowContext = CGPointMake([VeetleAppDelegate instance].window.width - keyboardHeight, 0.0);
            break;
    }

    CGPoint originOfKeyboardInTextFieldContext = [[VeetleAppDelegate instance].window convertPoint:originOfKeyboardInWindowContext toView:self.containerView.superview];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
    self.containerView.y = originOfKeyboardInTextFieldContext.y - self.containerView.height;
    [UIView commitAnimations];
}
于 2013-09-13T21:31:15.643 回答