UIScrollView scrollRectToVisible:animated:在iOS7上不考虑rect

问题描述 投票:9回答:5
[self.scrollView scrollRectToVisible:rect animated:YES];

没有人知道为什么它在iOS6.1和iOS7.0.4上可以很好地工作的原因,无论我发送哪种类型的rect作为参数,总是滚动到已经成为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:时自动滚动到它内部的第一个响应者。

ios iphone objective-c ios7 uiscrollview
5个回答
10
投票

将方法调用放入分配块中,这对我来说是个问题:

dispatch_async(dispatch_get_main_queue(), ^{ [self.scrollView scrollRectToVisible:rect animated:YES]; }); 我不完全理解为什么这行得通,而且我不确定这是否100%安全,但另一方面,与another answer by Rikkles中建议的仅将通话延迟0.1秒相比,这要安全得多。

我还不是线程问题的专家(但是),但是当UIKeyboardDidShowNotification发送时,似乎任何隐藏的系统方法都将覆盖滚动行为,这已经在主队列中了。因此,如果我们也将方法调用放在主队列上,那么它将在之后执行,因此会产生所需的效果。 (但这只是一个猜测。)

9
投票
但是,始终有效的是在延迟后执行选择器的古老技巧。只需将滚动代码放在自己的方法中,然后像下面这样调用该方法:

- (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]; }

并且它将在操作系统自动滚动后运行,并且您真是个黄金。


4
投票
这是因为我将contentSize设置为0(因为您不希望它滚动)。并且您应该至少设置1。

[scrollView setContentSize: CGSizeMake(1, self.view.frame.size.height)];

我希望这是解决方案;)


2
投票
Inside 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];
    }
}

0
投票
如果隐藏在键盘下,则下面的代码滚动到myView,假设您收到keyboardWillShow时调用了UIResponder.keyboardWillShowNotification函数。

Swift 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) } } }

© www.soinside.com 2019 - 2024. All rights reserved.