が特定の位置に達した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;
}