我发现最简单的解决方案就是这个(我不喜欢使用子视图来处理这类事情):
注册键盘框架更改通知(最好在 viewWillAppear 中注册并在 viewWillDisappear 中取消注册:):
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidChangeFrame:) name:UIKeyboardDidChangeFrameNotification object:nil];
然后在方法中:
- (void)keyboardDidChangeFrame:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect kbIntersectFrame = [window convertRect:CGRectIntersection(window.frame, kbFrame) toView:self.scrollView];
kbIntersectFrame = CGRectIntersection(self.bounds, kbIntersectFrame);
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbIntersectFrame.size.height, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
}
或者如果您想在更改 contentInset 后摆脱“跳转”:
- (void)keyboardDidChangeFrame:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect kbIntersectFrame = [window convertRect:CGRectIntersection(window.frame, kbFrame) toView:self.scrollView];
kbIntersectFrame = CGRectIntersection(self.scrollView.bounds, kbIntersectFrame);
// get point before contentInset change
CGPoint pointBefore = self.scrollView.contentOffset;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbIntersectFrame.size.height, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
// get point after contentInset change
CGPoint pointAfter = self.scrollView.contentOffset;
// avoid jump by settings contentOffset
self.scrollView.contentOffset = pointBefore;
// and now animate smoothly
[self.scrollView setContentOffset:pointAfter animated:YES];
}