Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animating UIScrollView contentInset causes jump stutter

I implemeted a custom refresh control (my own class, not a subclass), and for some reason since moving to iOS 8, setting the contentInset of the scroll view (specifically, UICollectionView) to start the refresh animation causes a weird jump/stutter. Here is my code:

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

Basically once the user releases to refresh, I animate the contentInset to the height of the refresh control. I figure the animation would reduce stuttering/jumpiness, which it did in iOS 7. But in iOS 8, when the scrollView is released from dragging, instead of just animating to the contentInset, the scroll view content jumps down from the point of release really quickly, and then animates up smoothly. I'm not sure if this is a bug in iOS 8 or what. I've also tried adding:

scrollView.contentOffset = CGPointZero; 

in the animation block, which didn't change anything.

Does anyone have any ideas? Any help would be highly appreciated. Thanks!

like image 597
ryanthon Avatar asked Sep 26 '14 01:09

ryanthon


2 Answers

I changed the method with my animation block to:

- (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;     }]; } 
like image 58
ryanthon Avatar answered Sep 19 '22 21:09

ryanthon


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

you can try this,the key is using two animation.

like image 31
user3044484 Avatar answered Sep 22 '22 21:09

user3044484