动画UIScrollView contentInset会导致跳转卡顿

rya*_*hon 30 uiscrollview ios uicollectionview pull-to-refresh

我实现了自定义刷新控件(我自己的类,而不是子类),并且由于某些原因,因为移动到iOS 8,设置滚动视图的contentInset(特别是UICollectionView)以启动刷新动画会导致奇怪的跳转/断断续续.这是我的代码:

- (void)containingScrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat scrollPosition = scrollView.contentOffset.y + scrollView.contentInset.top;

    if( scrollPosition > 0 || self.isRefreshing )
    {
        return;
    }

    CGFloat percentWidth = fabs( scrollPosition ) / self.frame.size.height / 2;

    CGRect maskFrame = self.maskLayer.frame;

    maskFrame.size.width = self.imageLayer.frame.size.width * percentWidth;

    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
    self.maskLayer.frame = maskFrame;
    [CATransaction commit];
}

- (void)containingScrollViewDidEndDragging:(UIScrollView *)scrollView
{
    if( ( self.maskLayer.frame.size.width >= self.imageLayer.frame.size.width ) && !self.isRefreshing )
    {
        self.isRefreshing = YES;
        [self setLoadingScrollViewInsets:scrollView];
        [self startAnimation];
        [self sendActionsForControlEvents:UIControlEventValueChanged];
    }
}

- (void)setLoadingScrollViewInsets:(UIScrollView *)scrollView
{
    UIEdgeInsets loadingInset = scrollView.contentInset;
    loadingInset.top += self.frame.size.height;

    UIViewAnimationOptions options = UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState;

    [UIView animateWithDuration:0.2 delay:0 options:options animations:^
    {
        scrollView.contentInset = loadingInset;
    }
    completion:nil];
}
Run Code Online (Sandbox Code Playgroud)

基本上,一旦用户释放刷新,我将contentInset设置为刷新控件的高度.我认为动画会减少口吃/跳跃,这是在iOS 7中做的.但是在iOS 8中,当scrollView从拖动中释放出来,而不是仅仅动画到contentInset时,滚动视图内容从发布点真实地跳下来快速,然后顺利动画.我不确定这是iOS 8中的错误还是什么.我也尝试过添加:

scrollView.contentOffset = CGPointZero;
Run Code Online (Sandbox Code Playgroud)

在动画块中,没有任何改变.

有没有人有任何想法?任何帮助将受到高度赞赏.谢谢!

rya*_*hon 36

我用动画块改变了方法:

- (void)setLoadingScrollViewInsets:(UIScrollView *)scrollView
{
    UIEdgeInsets loadingInset = scrollView.contentInset;
    loadingInset.top += self.view.frame.size.height;

    CGPoint contentOffset = scrollView.contentOffset;

    [UIView animateWithDuration:0.2 animations:^
    {
        scrollView.contentInset = loadingInset;
        scrollView.contentOffset = contentOffset;
    }];
}
Run Code Online (Sandbox Code Playgroud)

  • 为我工作!你摇滚.谢谢你把它放在这里. (3认同)
  • 你是对的,这确实解决了这个问题.看起来单独动画contentInset会导致动画干扰减速动画,这就是出现"跳跃"的原因.包含contentOffset从当前位置开始动画. (2认同)
  • 很棒的答案!导致此问题的原因是,在设置contentInset时,contentOffset也会根据contentInset的新值设置为一个值.因此,在设置contentInset后,将contentOffset恢复为旧值可解决问题.在iOS 9.0的应用程序中似乎不需要动画块. (2认同)

use*_*484 5

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    CGPoint point = scrollView.contentOffset;

    static CGFloat refreshViewHeight = 200.0f;

    if (scrollView.contentInset.top == refreshViewHeight) {
        //openning
        if (point.y>-refreshViewHeight) {
            //will close
            //?????animation??????!
            [UIView animateWithDuration:0 animations:NULL completion:^(BOOL finished) {
                [UIView animateWithDuration:0.25 animations:^{
                    scrollView.contentOffset = CGPointMake(0.0f, 0.0f);
                    scrollView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f);
                } completion:NULL];
            }];

        }
    }
    else{
        //closing
        static CGFloat openCriticalY = 40.0f;//?????????
        if(point.y<-openCriticalY){
            //will open
            [UIView animateWithDuration:0 animations:NULL completion:^(BOOL finished) {
                [UIView animateWithDuration:0.25 animations:^{
                    scrollView.contentInset = UIEdgeInsetsMake(refreshViewHeight, 0.0f, 0.0f, 0.0f);
                    scrollView.contentOffset = CGPointMake(0.0f, -refreshViewHeight);
                } completion:NULL];
            }];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以尝试这个,关键是使用两个动画.