如何检查键盘是否覆盖UIScrollView
内的第一响应者,可能是UITableView
还是UIScrollView
?请注意,UIModalPresentationFormSheet
不一定会涵盖整个viewController的视图,并且可能包含在模态视图中(CGRectContainsPoint
)。
我正在使用来自Apple's reference documentation and example的修改后的代码,但即使键盘明显覆盖了第一个响应者,convertRect:toView
也会返回false。很明显,我没有正确使用- (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;
}
。
此外,Apple的代码没有考虑到视图不是全屏,因此将scrollView的contentInset设置为键盘的整个高度并不是一个很好的解决方案 - 它应该只是插入部分键盘覆盖第一个响应者。
{{1}}
答案 0 :(得分:2)
如果没有进一步测试或深入研究逻辑,这条线似乎很奇怪:
CGRect kbRect = [self.scrollView convertRect:rect toView:nil];
键盘rect(包含在通知中)位于 window 坐标中,您可能希望将其转换为滚动视图坐标系。 [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
}];
}