2
0
Эх сурвалжийг харах

Revert UIView Animation from CAAnimation. Now they are all existed, and selected by this trigger (isCollectionViewAnimationBug). (#1407)

Frank 5 жил өмнө
parent
commit
4488bf1093

+ 3 - 0
MJRefresh/Base/MJRefreshHeader.h

@@ -24,6 +24,9 @@ NS_ASSUME_NONNULL_BEGIN
 
 /** 忽略多少scrollView的contentInset的top */
 @property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetTop;
+
+/** 默认是关闭状态, 如果遇到 CollectionView 的动画异常问题可以尝试打开 */
+@property (nonatomic) BOOL isCollectionViewAnimationBug;
 @end
 
 NS_ASSUME_NONNULL_END

+ 109 - 60
MJRefresh/Base/MJRefreshHeader.m

@@ -68,7 +68,6 @@ - (void)resetInset {
     }
 }
 
-
 - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
 {
     [super scrollViewContentOffsetDidChange:change];
@@ -114,6 +113,45 @@ - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
 
 - (void)setState:(MJRefreshState)state
 {
+    MJRefreshCheckState
+    
+    // 根据状态做事情
+    if (state == MJRefreshStateIdle) {
+        if (oldState != MJRefreshStateRefreshing) return;
+        
+        [self headerEndingAction];
+    } else if (state == MJRefreshStateRefreshing) {
+        [self headerRefreshingAction];
+    }
+}
+
+- (void)headerEndingAction {
+    // 保存刷新时间
+    [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:self.lastUpdatedTimeKey];
+    [[NSUserDefaults standardUserDefaults] synchronize];
+    
+    // 默认使用 UIViewAnimation 动画
+    if (!self.isCollectionViewAnimationBug) {
+        // 恢复inset和offset
+        [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
+            self.scrollView.mj_insetT += self.insetTDelta;
+            
+            if (self.endRefreshingAnimationBeginAction) {
+                self.endRefreshingAnimationBeginAction();
+            }
+            // 自动调整透明度
+            if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0;
+        } completion:^(BOOL finished) {
+            self.pullingPercent = 0.0;
+            
+            if (self.endRefreshingCompletionBlock) {
+                self.endRefreshingCompletionBlock();
+            }
+        }];
+        
+        return;
+    }
+    
     /**
      这个解决方法的思路出自 https://github.com/CoderMJLee/MJRefresh/pull/844
      修改了用+ [UIView animateWithDuration: animations:]实现的修改contentInset的动画
@@ -123,72 +161,85 @@ - (void)setState:(MJRefreshState)state
      同时, 处理了 Refreshing 中的动画替换.
     */
     
-    MJRefreshCheckState
+    // 由于修改 Inset 会导致 self.pullingPercent 联动设置 self.alpha, 故提前获取 alpha 值, 后续用于还原 alpha 动画
+    CGFloat viewAlpha = self.alpha;
     
-    // 根据状态做事情
-    if (state == MJRefreshStateIdle) {
-        if (oldState != MJRefreshStateRefreshing) return;
-        // 保存刷新时间
-        [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:self.lastUpdatedTimeKey];
-        [[NSUserDefaults standardUserDefaults] synchronize];
+    self.scrollView.mj_insetT += self.insetTDelta;
+    // 禁用交互, 如果不禁用可能会引起渲染问题.
+    self.scrollView.userInteractionEnabled = NO;
 
-        // 由于修改 Inset 会导致 self.pullingPercent 联动设置 self.alpha, 故提前获取 alpha 值, 后续用于还原 alpha 动画
-        CGFloat viewAlpha = self.alpha;
-        
-        self.scrollView.mj_insetT += self.insetTDelta;
+    //CAAnimation keyPath 不支持 contentInset 用Bounds的动画代替
+    CABasicAnimation *boundsAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"];
+    boundsAnimation.fromValue = [NSValue valueWithCGRect:CGRectOffset(self.scrollView.bounds, 0, self.insetTDelta)];
+    boundsAnimation.duration = MJRefreshSlowAnimationDuration;
+    //在delegate里移除
+    boundsAnimation.removedOnCompletion = NO;
+    boundsAnimation.fillMode = kCAFillModeBoth;
+    boundsAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+    boundsAnimation.delegate = self;
+    [boundsAnimation setValue:MJRefreshHeaderRefreshing2IdleBoundsKey forKey:@"identity"];
+
+    [self.scrollView.layer addAnimation:boundsAnimation forKey:MJRefreshHeaderRefreshing2IdleBoundsKey];
+    
+    if (self.endRefreshingAnimationBeginAction) {
+        self.endRefreshingAnimationBeginAction();
+    }
+    // 自动调整透明度的动画
+    if (self.isAutomaticallyChangeAlpha) {
+        CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+        opacityAnimation.fromValue = @(viewAlpha);
+        opacityAnimation.toValue = @(0.0);
+        opacityAnimation.duration = MJRefreshSlowAnimationDuration;
+        opacityAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+        [self.layer addAnimation:opacityAnimation forKey:@"MJRefreshHeaderRefreshing2IdleOpacity"];
+
+        // 由于修改了 inset 导致, pullingPercent 被设置值, alpha 已经被提前修改为 0 了. 所以这里不用置 0, 但为了代码的严谨性, 不依赖其他的特殊实现方式, 这里还是置 0.
+        self.alpha = 0;
+    }
+}
+
+- (void)headerRefreshingAction {
+    // 默认使用 UIViewAnimation 动画
+    if (!self.isCollectionViewAnimationBug) {
+        MJRefreshDispatchAsyncOnMainQueue({
+            [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+                if (self.scrollView.panGestureRecognizer.state != UIGestureRecognizerStateCancelled) {
+                    CGFloat top = self.scrollViewOriginalInset.top + self.mj_h;
+                    // 增加滚动区域top
+                    self.scrollView.mj_insetT = top;
+                    // 设置滚动位置
+                    CGPoint offset = self.scrollView.contentOffset;
+                    offset.y = -top;
+                    [self.scrollView setContentOffset:offset animated:NO];
+                }
+            } completion:^(BOOL finished) {
+                [self executeRefreshingCallback];
+            }];
+        })
+        return;
+    }
+    
+    if (self.scrollView.panGestureRecognizer.state != UIGestureRecognizerStateCancelled) {
+        CGFloat top = self.scrollViewOriginalInset.top + self.mj_h;
         // 禁用交互, 如果不禁用可能会引起渲染问题.
         self.scrollView.userInteractionEnabled = NO;
-        //CAAnimation keyPath 不支持 contentInset 用Bounds的动画代替
+
+        // CAAnimation keyPath不支持 contentOffset 用Bounds的动画代替
         CABasicAnimation *boundsAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"];
-        boundsAnimation.fromValue = [NSValue valueWithCGRect:CGRectOffset(self.scrollView.bounds, 0, self.insetTDelta)];
-        boundsAnimation.duration = MJRefreshSlowAnimationDuration;
+        CGRect bounds = self.scrollView.bounds;
+        bounds.origin.y = -top;
+        boundsAnimation.fromValue = [NSValue valueWithCGRect:self.scrollView.bounds];
+        boundsAnimation.toValue = [NSValue valueWithCGRect:bounds];
+        boundsAnimation.duration = MJRefreshFastAnimationDuration;
         //在delegate里移除
         boundsAnimation.removedOnCompletion = NO;
         boundsAnimation.fillMode = kCAFillModeBoth;
         boundsAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
         boundsAnimation.delegate = self;
-        [boundsAnimation setValue:MJRefreshHeaderRefreshing2IdleBoundsKey forKey:@"identity"];
-
-        [self.scrollView.layer addAnimation:boundsAnimation forKey:MJRefreshHeaderRefreshing2IdleBoundsKey];
-        
-        if (self.endRefreshingAnimationBeginAction) {
-            self.endRefreshingAnimationBeginAction();
-        }
-        // 自动调整透明度的动画
-        if (self.isAutomaticallyChangeAlpha) {
-            CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
-            opacityAnimation.fromValue = @(viewAlpha);
-            opacityAnimation.toValue = @(0.0);
-            opacityAnimation.duration = MJRefreshSlowAnimationDuration;
-            opacityAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
-            [self.layer addAnimation:opacityAnimation forKey:@"MJRefreshHeaderRefreshing2IdleOpacity"];
-
-            // 由于修改了 inset 导致, pullingPercent 被设置值, alpha 已经被提前修改为 0 了. 所以这里不用置 0, 但为了代码的严谨性, 不依赖其他的特殊实现方式, 这里还是置 0.
-            self.alpha = 0;
-        }
-    } else if (state == MJRefreshStateRefreshing) {
-        if (self.scrollView.panGestureRecognizer.state != UIGestureRecognizerStateCancelled) {
-            CGFloat top = self.scrollViewOriginalInset.top + self.mj_h;
-            // 禁用交互, 如果不禁用可能会引起渲染问题.
-            self.scrollView.userInteractionEnabled = NO;
-
-            // CAAnimation keyPath不支持contentOffset 用Bounds的动画代替
-            CABasicAnimation *boundsAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"];
-            CGRect bounds = self.scrollView.bounds;
-            bounds.origin.y = -top;
-            boundsAnimation.fromValue = [NSValue valueWithCGRect:self.scrollView.bounds];
-            boundsAnimation.toValue = [NSValue valueWithCGRect:bounds];
-            boundsAnimation.duration = MJRefreshFastAnimationDuration;
-            //在delegate里移除
-            boundsAnimation.removedOnCompletion = NO;
-            [boundsAnimation setValue:MJRefreshHeaderRefreshingBoundsKey forKey:@"identity"];
-            boundsAnimation.fillMode = kCAFillModeBoth;
-            boundsAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
-            boundsAnimation.delegate = self;
-            [self.scrollView.layer addAnimation:boundsAnimation forKey:MJRefreshHeaderRefreshingBoundsKey];
-        } else {
-            [self executeRefreshingCallback];
-        }
+        [boundsAnimation setValue:MJRefreshHeaderRefreshingBoundsKey forKey:@"identity"];
+        [self.scrollView.layer addAnimation:boundsAnimation forKey:MJRefreshHeaderRefreshingBoundsKey];
+    } else {
+        [self executeRefreshingCallback];
     }
 }
 
@@ -201,8 +252,7 @@ - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
         if (self.endRefreshingCompletionBlock) {
             self.endRefreshingCompletionBlock();
         }
-    }
-    if ([identity isEqualToString:MJRefreshHeaderRefreshingBoundsKey]) {
+    } else if ([identity isEqualToString:MJRefreshHeaderRefreshingBoundsKey]) {
         CGFloat top = self.scrollViewOriginalInset.top + self.mj_h;
         self.scrollView.mj_insetT = top;
         // 设置最终滚动位置
@@ -219,7 +269,6 @@ - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
     
     if ([self.scrollView.layer animationForKey:MJRefreshHeaderRefreshingBoundsKey]) {
         [self.scrollView.layer removeAnimationForKey:MJRefreshHeaderRefreshingBoundsKey];
-        
     }
 }