CAAnimation滚动超出范围时停止

问题描述 投票:0回答:2

我有一个无限旋转的UIImageView形式的自定义活动指示器。并将这个惊人的活动指示器放置在表格单元格中。

以这种方式实现动画:

CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: M_PI * 2.0];
animation.duration = 1.0f;
animation.repeatCount = INFINITY;

[self.layer addAnimation:animation forKey:@"SpinAnimation"];

最初,它的工作原理很漂亮...但是,当单元格滚动到表格的边界之外时,动画停止,并且我不知道如何重置它... /:

请帮助...提前非常感谢...:)

iphone ios objective-c core-animation
2个回答
2
投票

原因是旋转动画。当prepareForReuse进行工作您的应用程序进入后台模式。时,z键变为零。

考虑用手绘制活动指示器或尝试使用https://github.com/airbnb/lottie-ios之类的方法>

下面的方法

活动指示器可以正常工作,并且在滚动/单元格/背景模式下滚动良好

我尝试了rotation.z和基于CAReplicationLayer的解决方法-均在滚动/单元格/背景模式下均失败

progressLayer look

private func drawLoaderCircle() {

    let path = UIBezierPath(arcCenter: loaderViewCenter, radius: loaderCircleRadius, startAngle: 0, endAngle: 2 * .pi, clockwise: true).cgPath

    setupGrapes(endAngle: 310, path: path)
}

private func setupGrapes(endAngle: CGFloat, path: CGPath) {

    let step: CGFloat = 2
    var grapeAnimationDelay: CFTimeInterval = 0

    for i in stride(from: 0, to: endAngle, by: step) {

        let radians = i * .pi / 180

        let x = loaderViewCenter.x + loaderCircleRadius * cos(radians)
        let y = loaderViewCenter.y + loaderCircleRadius * sin(radians)

        let grapeLayer = CAShapeLayer()
        grapeLayer.frame = CGRect(x: 0, y: 0, width: circleWidth + 0.2, height: circleWidth + 0.2)
        grapeLayer.position = CGPoint(x: x, y: y)
        grapeLayer.cornerRadius = grapeLayer.frame.width / 2
        grapeLayer.backgroundColor = loaderColor.cgColor

        grapeAnimationDelay += Double(rotateDuration * Double(step) / 360)
        let rotateGrapeAnimation = CAKeyframeAnimation(keyPath: "position")
        rotateGrapeAnimation.path = path
        rotateGrapeAnimation.beginTime = grapeAnimationDelay
        rotateGrapeAnimation.calculationMode = .linear
        rotateGrapeAnimation.repeatCount = .infinity
        rotateGrapeAnimation.isRemovedOnCompletion = false
        rotateGrapeAnimation.duration = rotateDuration

        grapeLayer.add(rotateGrapeAnimation, forKey: nil)

        progressLayer.addSublayer(grapeLayer)
    }

}
        

[当重新使用相应的单元格时,似乎删除了此动画。至少,当我从animationDidStop返回出队单元格时,我得到了cellForItemAtIndexPath委托的回调。

我能想到的最简单的解决方法:

您的表视图数据源:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    if(cell && [cell conformsToProtocol:@protocol(CustomCellProtocol)])
    {
        [(id<CustomCellProtocol>)cell beforeDisplayed];
    }

    return cell;
}

您的单元格:

static NSString* const kSpinAnimationKey = @"SpinAnimation";

@interface CustomCell () <CustomCellProtocol>
@end

@implementation CustomCell

-(void)startSpinAnimation
{
    CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

    animation.fromValue = [NSNumber numberWithFloat:0.0f];
    animation.toValue = [NSNumber numberWithFloat: M_PI * 2.0];
    animation.duration = 1.0f;
    animation.repeatCount = INFINITY;

    [self.layer addAnimation:animation forKey:kSpinAnimationKey];
}

-(void)beforeDisplayed
{
    UIView* animatedView = self.contentView;
    if(![animatedView.layer animationForKey:kSpinAnimationKey])
    {
        [self startSpinAnimation];
    }
}

1
投票

[当重新使用相应的单元格时,似乎删除了此动画。至少,当我从animationDidStop返回出队单元格时,我得到了cellForItemAtIndexPath委托的回调。

© www.soinside.com 2019 - 2024. All rights reserved.