【问题标题】:Scroll UITableView with CABasicAnimation in uitableviewcell makes the animation jumpy在 uitableviewcell 中使用 CABasicAnimation 滚动 UITableView 使动画跳动
【发布时间】:2023-04-09 23:52:01
【问题描述】:

我有一个 UITableView,在它的 UITableViewCells 内我正在使用 CABasicAnimation 为图表饼图层设置动画。

问题是,如果我在为图层设置动画的同时滚动表格视图 - 图层动画会变得跳跃而不是“干净”。

图层的动画开始于:

tableView:willDisplayCell:forRowAtIndexPath:

也使用 dequeueReusableCellWithIdentifier:

static NSString *cellIdentifier = @"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(!cell)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    ...
}
...
return cell;

安排计时器更新图表进度:

- (void)startAnimation 
{
self.elapsedTimeTimer = nil;
self.elapsedTimeTimer = [NSTimer scheduledTimerWithTimeInterval:0.02
                                                             target:self
                                                           selector:@selector(updateProgress)
                                                           userInfo:nil
                                                            repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.elapsedTimeTimer
                             forMode:NSRunLoopCommonModes];
}

- (void)updateProgress
{
    if(!self.didEndProgress)
       self.progress += 0.01;

    if(self.progress >= self.finalPercents/100)
    {
        [self.elapsedTimeTimer invalidate];
        self.elapsedTimeTimer = nil;
    }
}

层实现:

@implementation CircleGraphLayer
@dynamic progress;

+ (BOOL)needsDisplayForKey:(NSString *)key {
return [key isEqualToString:@"progress"] || [super needsDisplayForKey:key];
}

- (id<CAAction>)actionForKey:(NSString *)aKey {
if ([aKey isEqualToString:@"progress"]) {

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:aKey];
    animation.fromValue = [self.presentationLayer valueForKey:aKey];
    return animation;
}
return [super actionForKey:aKey];
}

- (void)drawInContext:(CGContextRef)context {

CGRect circleRect = CGRectInset(self.bounds, 1, 1);
CGContextClearRect(context, circleRect);

CGColorRef borderColor = [[UIColor colorWithWhite:1.0 alpha:0.4] CGColor];
CGColorRef backgroundColor = [[UIColor clearColor] CGColor]; //[[UIColor colorWithWhite: 1.0 alpha: 0.15] CGColor];

CGContextSetFillColorWithColor(context, backgroundColor);
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextSetLineWidth(context, 1.0f);

CGContextFillEllipseInRect(context, circleRect);
CGContextStrokeEllipseInRect(context, circleRect);

CGFloat radius = MIN(CGRectGetMidX(circleRect), CGRectGetMidY(circleRect));
CGPoint center = CGPointMake(radius, CGRectGetMidY(circleRect));
CGFloat startAngle = -M_PI / 2;
CGFloat endAngle = self.progress * 2 * M_PI + startAngle;
CGContextSetFillColorWithColor(context, borderColor);
CGContextMoveToPoint(context, center.x, center.y);
CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0);
CGContextClosePath(context);
CGContextFillPath(context);
[super drawInContext:context];
}
@end

我们将不胜感激。

【问题讨论】:

  • 仪器告诉你什么?
  • 我应该选择哪个模板在 Instruments 中运行它?核心动画?

标签: ios objective-c uitableview cabasicanimation


【解决方案1】:

由于我的声誉,我无法发表评论。这不是主要问题的答案,而是代码中一个小错误的解决方案:如果使用[NSTimer scheduledTimerWithTimeInterval:...] 而不是[NSTimer timerWithTimeInterval:...],则无需将计时器添加到[NSRunLoop currentRunLoop]。请参阅NSTimer Class Reference 中的“在运行循环中调度计时器”部分。 希望对您有所帮助。

【讨论】:

  • 其实可以看到OP正在给NSRunLoopCommonModes添加定时器。当您使用 scheduledTimer... 时,它会被添加到 NSDefaultRunLoopMode,因此两者不会相同。
最近更新 更多