动画CAGradientLayer的位置在物业竣工后一个UIScrollView面具重置(Anima

2019-09-18 04:20发布

我想一个动画的位置CAGradientLayer时收缩UIScrollView已经达到了一定的地位。 我有我的梯度设置为面具UIScrollView ,并调整渐变的locations属性来扩展位作为滚动视图滚动。 这只是正常的我,除了当我尝试动画更改了位置。 当我执行动画-无论是作为一个明确的CABasicAnimation或隐式-动画执行正确,但无论出于何种原因,一旦动画完成它,然后改变了我的梯度(无动画)的一些其他非零起点的位置和终点。 它使用相同的值,每一次这样做,并且这些值不是在我的代码的任何规定。

我是相当新的Core Animation的,所以也许我失去了一些东西,但据我可以告诉我的代码是正确的。 我也试着等待执行的动画,考虑到我的滚动任何时间问题,但这并没有帮助。

这里是我的代码(相关部分,反正):

- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    gradientMask.position = CGPointMake(currentPageOffset, 0.0f);
    gradientMask.bounds = self.scrollView.bounds;
    [CATransaction commit];

    _animateGradientShrinkOnScroll = YES;

    // Reset scrollView contentOffset (I'm doing infinite paging)
    ...
}

- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat offset = self.scrollView.contentOffset.x;
    CGFloat relativeOffset = offset - currentPageOffset;

    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    gradientMask.position = self.scrollView.contentOffset;
    if (_animateGradientShrinkOnScroll)
        [CATransaction commit]; // if animating, set position w/o animation first

    CGFloat leftLength = ABS(relativeOffset);
    CGFloat rightLength = ABS(relativeOffset);

    CGFloat maxLength = [self maxGradientLength];
    leftLength = MIN((leftLength / 2), maxLength);
    rightLength = MIN((rightLength / 2), maxLength);

    // When animating, this effectively always goes from non-zero lengths to zero lengths,
    // and I've verified this by logging the values used.
    [self setGradientLeftLength:leftLength rightLength:rightLength animated:_animateGradientShrinkOnScroll];

    if (!_animateGradientShrinkOnScroll)
        [CATransaction commit];
    _animateGradientShrinkOnScroll = NO;
}

- (void) setGradientLeftLength:(CGFloat)leftLength rightLength:(CGFloat)rightLength animated:(BOOL)animated {
    CGFloat startRatio = MAX((leftLength / gradientMask.bounds.size.width), 0);
    CGFloat endRatio = 1.0f - MAX((rightLength / gradientMask.bounds.size.width), 0);

    NSArray *locations = [NSArray arrayWithObjects:
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:startRatio],
                          [NSNumber numberWithFloat:endRatio],
                          [NSNumber numberWithFloat:1.0f], nil];

    if (animated) {
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"locations"];
        animation.toValue = locations;
        [gradientMask addAnimation:animation forKey:kGradientMaskAnimationShrink];
    }
    else
        gradientMask.locations = locations;
}

Answer 1:

添加动画到层不会改变图层的属性。 它只是动画层的在屏幕上亮相。 一旦动画从层中除去,所述层是基于其属性重绘。 所以,你需要改变图层的属性,然后应用动画。 在您if声明,这样做:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"locations"];
animation.fromValue = gradientMask.locations;
animation.toValue = locations;
gradientMask.locations = locations;
[gradientMask addAnimation:animation forKey:animation.keyPath];

为了更好地理解,观看了“核心动画纲要”视频2011 WWDC 。 这是非常有帮助的。



文章来源: Animating CAGradientLayer's locations property in a UIScrollView mask resets after completion