当键盘显示并覆盖它时,我试图滚动到 UITextView 中的插入符号。不幸的是,它只有在我不为它制作动画时才有效,尽管 Apple 在 Notes 应用程序中做了同样的事情。我正在使用Apple 文档中解释的相同方法。
这是代码。它位于一个孤立的项目中,可以在没有任何其他干扰的情况下对其进行测试。只有一个添加了 UITextView 的视图控制器。我正在模拟器和设备上的 iOS 7 上对此进行测试。
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedKeyboardDidShowNotification:) name:UIKeyboardDidShowNotification object:nil];
}
- (void)receivedKeyboardDidShowNotification:(NSNotification *)notification {
CGRect keyboardBounds = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
CGFloat keyboardDistanceFromBottomOfScreen = screenHeight - CGRectGetMinY(keyboardBounds);
UITextView *textView = self.textView;
UIEdgeInsets contentInset = textView.contentInset;
contentInset.bottom += keyboardDistanceFromBottomOfScreen;
textView.contentInset = contentInset;
textView.scrollIndicatorInsets = contentInset;
CGRect caretRect = [textView caretRectForPosition:textView.selectedTextRange.end];
[textView scrollRectToVisible:caretRect animated:YES];
}
如果我将animated
最后一行中的参数设置为NO
,则效果很好(当然,没有动画,这是我不想要的)。通过YES
会产生奇怪的行为。大多数情况下,视图不会滚动或仅滚动几个像素,但有时它会产生我想要的行为,因此结果是随机的。
我试图计算插入符号的偏移量并使用setContentOffset:animated:
方法而不是scrollRectToVisible:animated:
,但结果是一样的。如果animated
是,它会起作用NO
。有了YES
它会产生同样奇怪的结果。
更奇怪的是,在第二个解决方案中,该行上的断点被击中了两次,尽管通知只传递了一次。上一行或我在其后添加的一行上的断点(什么都不做,只是一个用于测试的日志语句)只被击中一次。为了增加更多的陌生感,在三行上放置日志断点会产生以下结果:
Line before
Buggy line
Line after
Buggy line
所以第二次上线就出问题了。看着检查器,看起来所有的局部变量都不再在范围内了。
我还尝试将两种解决方案的代码放在另一种方法中,并在延迟后调用它,performSelector:withObject:afterDelay:
但没有任何改变,即使是像 1 秒这样的长时间延迟。在第一个解决方案中,虽然没有发生断点上的双重命中。
在这一点上,我用完了解决方案,这对我来说似乎是一个 iOS 错误,但正如我所说,它在 Notes 应用程序中有效,所以至少有一个解决方案。
编辑:我做了更多调查,只有当文本视图是第一响应者并且显示键盘时才会发生错误(我不能说哪个负责)。如果我从代码而不是键盘通知触发 scrollRectToVisible:animated:
,则动画效果很好。但是,如果我第一次调用[textView becomeFirstResponder]
显示键盘的 ,动画会再次中断。