UIScrollView setContentInset导致ios8中的滚动跳过

时间:2014-09-23 11:49:56

标签: objective-c uiscrollview ios8

在scrollview底部创建一个pull to refresh机制时遇到问题。代码在iOS7中运行非常流畅,但在iOS8中,scrollview会立即跳过,然后动画到正确的位置。

我正在跟踪滚动,直到它超出kPullToRefreshHeightPX(在我的情况下这是40px),并设置一个标志然后插入释放,并触发内容刷新。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (_webShouldInsetScrollView == NO && (scrollView.contentOffset.y > ((scrollView.contentSize.height - scrollView.frame.size.height) + kPullToRefreshHeightPX)))
    {
        _webShouldInsetScrollView = YES;
    }
}

如果在结束拖动时我们拖动了超出我们的刷新距离,那么我们插入(并运行我们的小刷新动画)并显示下一个结果页面。

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (_webShouldInsetScrollView)
    {
        [UIView animateWithDuration:0.2 animations:^{
                [scrollView setContentInset:UIEdgeInsetsMake(0.0f, 0.0f, kPullToRefreshHeightPX, 0.0f)];
        } completion:^(BOOL finished) {
        }];

        [self performSelector:@selector(showNextResultsPage) withObject:nil afterDelay:1.0f];
    }
}

我已经在iOS8中阅读了UIScrollViews的其他问题,其中一个在iOS7中谈到automaticallyAdjustsScrollViewInsets被设置为false,但在iOS8中默认为true,但这对上面的代码没有影响。有没有其他人有类似的经历,并找到了解决方法?

3 个答案:

答案 0 :(得分:7)

解决了这个问题,:D

CGPoint offset = scrollView.contentOffset;
[scrollView setContentInset:UIEdgeInsetsMake(topInset, 0, 0, 0)];
scrollView.contentOffset = offset;

答案 1 :(得分:1)

我们有完全相同的问题......

在深入挖掘之后,我已经看到,最初以某种方式将目标插入设置在某处:

让我说我将tableView从200下拉到500 - 在scrollViewDidEndDragging上我触发了这样的动画:

 [UIView animateWithDuration:0.2
                          delay:0
                        options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState
                     animations:^{
                         scrollView.contentInset = targetInset;
                     }
                     completion:nil];

    [self sendActionsForControlEvents:UIControlEventValueChanged];

在设置正确的动画值之前,targetValue(250)设置一次,而不是平滑地从500返回到-let&250s的平滑动画......

我的解决方法是在开始动画之前设置动画标志。我在完整块中重置它...滚动条检查此标志并仅在动画结束时设置targetValue:

_isAnimatingInset = YES;
_currentTopInsetTarget = targetInset.top;

 [UIView animateWithDuration:0.2
                          delay:0
                        options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState
                     animations:^{
                         scrollView.contentInset = targetInset;
                     }
                     completion:^(BOOL finished) {
                         //Workaround for a iOS8-Bug see property-comment for further infos
                         _isAnimatingInset = NO;
                         scrollView.contentInset = targetInset;
                     }];

    [self sendActionsForControlEvents:UIControlEventValueChanged];

这样可以最大限度地减少效果,但不幸的是,此刻我无法阻止设置这个错误的值(相反,我将其重置为之前也会导致动画中出现小的hickUp ...)

答案 2 :(得分:0)

经过一段时间的搜索,我找不到合适的答案。通过github中的几个pull-to-referh实现(在iOS8模拟器中运行它们),我可以看到所有这些实现在iOS8上完全相同的跳跃。

这是我能够做到的,以尽量减少这种影响。回顾一下问题:当我们的刷新控件需要保持可见时,我们会尝试将contentInset调整为超级视图scrollView中控制高度的值。更改contentInset会触发滚动内容(在iOS7和iOS8上),在iOS8上,此跳转非常明显。

我从自定义pull-to-refres的基本startRefresh函数中删除了contentInset中的任何更改。在您的情况下 - 从UIView animateWithDuration:0.2 animations删除整个scrollViewDidEndDragging

并在scrollViewDidScroll处理程序(开头)中添加类似内容:

if (self.isRefreshing) {
    // If we already scrolled back past the point of our control height and we haven't changed
    // contentInset yet - update it

    if (scrollView.contentOffset.y > -CONTROL_HEIGHT && scrollView.contentInset.top == 0) {
        UIEdgeInsets inset = scrollView.contentInset;
        inset.top = CONTROL_HEIGHT;
        scrollView.contentInset = inset;
    }
    return;
}

...