animationUIScrollView contentInset导致跳跃口吃

我实现了一个自定义的刷新控制(我自己的类,而不是一个子类),出于某种原因,因为移动到iOS 8,设置滚动视图(具体来说,UICollectionView)的contentInset开始刷新animation会导致一个奇怪的跳跃/口吃。 这是我的代码:

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

基本上,一旦用户释放刷新,我将contentInsetanimation到刷新控件的高度。 我认为animation会减lessiOS 7中的口吃/跳跃。但是,在iOS 8中,当scrollView从拖动中释放时,而不是animation到contentInset,滚动视图内容会从释放点跳下快速,然后顺利进行animation。 我不确定这是否是iOS 8中的错误或者是什么。 我也试过添加:

 scrollView.contentOffset = CGPointZero; 

在animation块中,没有任何改变。

有没有人有任何想法? 任何帮助将不胜感激。 谢谢!

我改变了我的animation块的方法:

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

你可以试试这个,关键是使用两个animation。

为了消除跳跃,ryanthon的答案将做的伎俩。 在iOS9.0的应用程序中,甚至不需要animation块来删除跳转,只需在设置contentInset之后重置contentOffset即可。

如果你想在隐藏刷新视图的时候控制tableView的滚动速度,在user3044484的回答中双重animation块的窍门会做魔术,一个animation块是不够的。

 if (self.tableView.contentInset.top == 0) { UIEdgeInsets tableViewInset = self.tableView.contentInset; tableViewInset.top = -1.*kTableHeaderHeight; [UIView animateWithDuration: 0 animations: ^(void){} completion:^(BOOL finished) { [UIView animateWithDuration: 0.5 animations:^{ //no need to set contentOffset, setting contentInset will change contentOffset accordingly. self.tableView.contentInset = tableViewInset; }]; }]; } 

我有同样的问题,并将我的animation块移到…

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView

代替方法。 不完美,但我不能确定问题呢。 看起来像scrollView的-layoutSubviews方法在iOS8下更频繁地调用,导致跳动animation。

两种解决scheme

  1. 开始加载时禁用弹跳,加载完成时启用弹跳
  2. 在开始加载时设置内容填充后,请将内容偏移设置为一个常数值

我已经解决了: –

  • 当ContentInset被更新为contentOffsetY时禁用反弹。
  • 跟踪contentOffset并更新到tableView ContentInset。
  var contentOffsetY:CGFloat = 100 func tracScrollContent(location: UIScrollView) { if(location.contentOffset.y == -contentOffsetY ) { tblView.isScrollEnabled = true tblView.bounces = false tblView.contentInset = UIEdgeInsets(top: contentOffsetY, left: 0, bottom: 0, right: 0) }else if(location.contentOffset.y >= 0 ){ tblView.bounces = true tblView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) } } 

Github Demo Swift-3

animation- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView不幸的是不适合我。 滚动视图反弹。

根据界限自动更改UIScrollView与内容插入这似乎像一个iOS8的bug …