滚动越界时CAAnimation停止

时间:2013-09-15 21:14:11

标签: iphone ios objective-c core-animation

我有一个无限旋转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"];



起初,它工作得很漂亮...但是当单元格从表格的边界滚动时,动画停止,我不知道如何重置它... /:

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

2 个答案:

答案 0 :(得分:1)

似乎在重复使用相应的单元格时会删除此动画。至少,当我从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 :(得分:1)

原因是旋转动画。当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)
    }

}