[self.scrollView scrollRectToVisible:rect animated:YES];
有没有人知道为什么这在iOS6.1和iOS7.0上完全正常工作总是滚动到已成为firstResponder的UITextField,无论我作为参数发送什么样的矩形?
CGRect rect = CGRectMake(0, self.scrollView.frame.size.height - 1, 320, 1);
[self.scrollView scrollRectToVisible:rect animated:YES];
当显示键盘时,由于UIScrollView内的UITextField已成为iOS6.1上的第一响应者,此代码将UIScrollView滚动到底部,但在iOS7.0.4上滚动它以便UITextFiled可见。
正如我想的那样,iOS7 SDK中的UIScrollView无论如何,当scrollRectToVisible:animated:被调用时,自动滚动到内部的第一个响应者。
答案 0 :(得分:10)
我怀疑大多数开发人员正在将scrollRectToVisible:Animated:
与系统键盘通知结合使用,如Apple Docs here中所述。对我来说,Apple提供的示例代码并没有起作用(好吧,只有一半是这样的。)
将方法调用放在调度块中为我解决了问题:
dispatch_async(dispatch_get_main_queue(), ^{
[self.scrollView scrollRectToVisible:rect animated:YES];
});
我不完全理解为什么会这样做,我不确定这是否100%安全,但另一方面,感觉比仅仅延迟0.1秒的呼叫更安全{ {3}}
我还不是线程问题的专家(但是)但是当发送UIKeyboardDidShowNotification
时,似乎任何隐藏的系统方法都会覆盖滚动行为。因此,如果我们将方法调用放在主队列上,它将在之后执行,从而产生所需的效果。 (但这只是猜测。)
答案 1 :(得分:9)
在iOS 8(可能还有7个)上,操作系统在runloop操作的尾端自动滚动到UITextField,就在它返回到监听用户输入之前。
在OS自动滚动之后和用户输入之前,我没有找到任何方法进入。 UIKeyboardWillShowNotification
和UIKeyboardDidShowNotification
都不是可行的钩子。
然而,总是有效的是延迟后执行选择器的好老把戏。只需将滚动代码放在自己的方法中,然后调用该方法:
- (void)keyboardDidShow:(NSNotification*)aNotification {
// ... all code to choose the view you want ...
[self performSelector:@selector(moveToView:) withObject:visibleView afterDelay:0.1];
}
- (void)moveToView:(UIView *)aView {
[self.scView scrollRectToVisible:aView.frame animated:YES];
}
这将在操作系统自动滚动后运行,而你是黄金。
答案 2 :(得分:4)
之前我遇到过这个问题。不是一件容易的事,但肯定很无聊。
这是因为我将contentSize设置为0(因为您不希望它滚动)。你应该至少设置1个。
[scrollView setContentSize: CGSizeMake(1, self.view.frame.size.height)];
我希望这是解决方案;)
答案 3 :(得分:2)
我找到了解决这个问题的方法,但它不是一个漂亮的问题。为了将滚动视图滚动到所需位置,您必须同时注册keyboardWillShow和keyboardDidShow通知。然后将用于设置滚动视图的插图的代码放置在keyboardWillShowNotification的观察者的选择器中,并将用于将滚动视图滚动到所需位置的代码放置在keyboardDidShowNotification的观察者'选择器。这就是我所拥有的:
在viewDidLoad中:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
通知方法:
- (void) keyboardWillShow: (NSNotification*) aNotification;
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
float kbHeight = kbSize.height < kbSize.width ? kbSize.height : kbSize.width;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbHeight, 0.0);
_scrollView.contentInset = contentInsets;
_scrollView.scrollIndicatorInsets = contentInsets;
}
-(void)keyboardDidShow:(NSNotification*)notification
{
CGRect aRect = CGRectMake(0, 0, _scrollView.frame.size.width, _scrollView.frame.size.height - _scrollView.frame.origin.y - self.scrollView.contentInset.bottom);
CGRect scrollFrame = CGRectMake(self.loginView.frame.origin.x + self.loginButton.frame.origin.x, self.loginView.frame.origin.y + self.loginButton.frame.origin.y, self.loginButton.frame.size.width, self.loginButton.frame.size.height);
if (!CGRectContainsRect(aRect, scrollFrame)) {
[_scrollView scrollRectToVisible:scrollFrame animated:YES];
}
}
答案 4 :(得分:0)
我一直在关注Apple文档,但没有成功。然后,我尝试在自己的scrollView上调用setContentOffset(_:animated:)
,而不是scrollRectToVisible(_:animated:)
,这使它起作用。
如果隐藏在键盘下,则下面的代码滚动到myView
,假设您收到keyboardWillShow
时调用了UIResponder.keyboardWillShowNotification
函数。
快速5
@objc private func keyboardWillShow(_ notification: Notification) {
if let keyboardHeight = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size.height {
scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardHeight, right: 0)
let visibleViewFrame = myView.frame
var scrollViewFrame = scrollView.frame
scrollViewFrame.size.height -= keyboardHeight
if !scrollViewFrame.contains(visibleViewFrame) {
scrollView.setContentOffset(CGPoint(x: 0, y: visibleViewFrame.origin.y), animated: true)
}
}
}