1

如何检查键盘是否覆盖了 a 内的第一响应者,UIScrollView这可能是也可能不是UITableView?请注意,UIScrollView不一定会覆盖整个 viewController 的视图,并且可能包含在模态视图 ( UIModalPresentationFormSheet) 中。

我正在使用Apple 参考文档和示例中的修改后的代码,但CGRectContainsPoint即使键盘明显覆盖了第一响应者,也会返回 false。很明显我没有convertRect:toView正确使用。

此外,Apple 的代码没有考虑到视图不是全屏的,因此将 scrollView 的 contentInset 设置为键盘的全高并不是一个很好的解决方案——它应该只插入键盘覆盖的部分第一个响应者。

- (void)keyboardWasShown:(NSNotification*)aNotification

{
    // self.scrollView can be a tableView or not. need to handle both
    UIView *firstResponderView = [self.scrollView findFirstResponder];
    if (!firstResponderView)
        return;

    NSDictionary* info = [aNotification userInfo];
    CGRect rect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    // convertRect:toView? convertRect:fromView? Always confusing
    CGRect kbRect = [self.scrollView convertRect:rect toView:nil];
    CGRect viewRect = [self.scrollView convertRect:firstResponderView.bounds toView:nil];

    // doesn't work. convertRect misuse is certainly to blame 
    if (!CGRectContainsPoint(kbRect, firstResponderView.frame.origin))
        return;

    // Only inset to the portion which the keyboard covers?
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbRect.size.height, 0.0);
    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
}
4

1 回答 1

2

如果没有进一步测试或深入了解逻辑,这条线似乎很奇怪:

CGRect kbRect = [self.scrollView convertRect:rect toView:nil];

键盘矩形(包含在通知中)位于窗口坐标中,您可能希望将其转换为滚动视图坐标系。[viewA convertRect:rect toView:viewB]将 rect 从 viewA 的坐标系转换为 viewB 的坐标系,因此您实际上正在做与您应该做的相反的事情(正如您所怀疑的那样)。

我通常做的是这样的:

- (void)keyboardWillShow:(NSNotification *)aNotification
{
    NSDictionary *info = [aNotification userInfo];
    CGRect kbRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    kbRect = [self.view.window convertRect:kbRect toView:self.view];    // convert to local coordinate system, otherwise it is in window coordinates and does not consider interface orientation
    _keyboardSize = kbRect.size;    // store for later use

    [UIView animateWithDuration:0.25 animations:^{
        UIEdgeInsets insets = UIEdgeInsetsMake(0.0f, 0.0f, MAX(0.0f, CGRectGetMaxY(_tableView.frame) - CGRectGetMinY(kbRect)), 0.0f);    // NB: _tableView is a direct subview of self.view, thus _tableView.frame and kbRect are in the same coordinate system
        _tableView.contentInset = insets;
        _tableView.scrollIndicatorInsets = insets;
        [self scrollToActiveTextField];    // here I adapt the content offset to ensure that the active text field is fully visible
    }];
}
于 2013-10-06T21:43:02.007 回答