如何在UITableViewCell中实现UIProgressBar动画?
解决UITableViewCell中UIProgressBar动画不生效的问题
首先得指出你代码里的两个关键问题,这也是动画没效果的核心原因:
UIProgressView的value范围错误:UIProgressBar(准确说是UIProgressView)的
value属性是0.0到1.0之间的浮点数,代表0%到100%的进度。你直接设置成55.f完全超出了有效范围,哪怕没有动画,这个值也不会正确显示出来。动画时机不对:在
tableView:cellForRowAtIndexPath:方法里,cell要么是刚被初始化,要么是从复用池里取出来,但此时它还没有被添加到UITableView的视图层级中。UIView的动画依赖于视图在渲染周期内,没有加入视图树的视图,动画是不会被触发执行的。
正确的实现方案
推荐用UITableView的willDisplayCell:forRowAtIndexPath:代理方法来执行动画——这个方法会在cell即将显示到屏幕上时调用,此时cell已经被加入视图层级,动画能正常生效。
步骤1:修正value值并实现代理方法
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { // 先判断cell类型 if ([cell isKindOfClass:[TableViewCellResults class]]) { TableViewCellResults *resultCell = (TableViewCellResults *)cell; // 重置进度条到初始状态,避免复用的cell带着旧进度 resultCell.progressBar.value = 0.0; // 执行动画,目标值用0-1的浮点数,比如55%就是0.55 [UIView animateWithDuration:10.f animations:^{ resultCell.progressBar.value = 0.55; }]; } }
步骤2:保持cellForRow的原有逻辑(只负责配置数据)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *cellId = @"TableViewCellResult"; TableViewCellResults *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; if (cell == nil) { cell = [[TableViewCellResults alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellId]; } // 这里只做cell的基础配置,不要放动画逻辑 return cell; }
另一种方案:在Cell内部处理动画
如果你想把动画逻辑封装在Cell类里,可以重写Cell的didMoveToSuperview方法,当Cell被添加到父视图(也就是UITableView)时触发动画:
在TableViewCellResults类中:
// 先给Cell加一个属性,用来存储目标进度值 @property (nonatomic, assign) CGFloat targetProgress; - (void)didMoveToSuperview { [super didMoveToSuperview]; // 只有当Cell被添加到父视图时才执行动画 if (self.superview) { self.progressBar.value = 0.0; [UIView animateWithDuration:10.f animations:^{ self.progressBar.value = self.targetProgress; }]; } }
然后在cellForRow中设置目标值:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *cellId = @"TableViewCellResult"; TableViewCellResults *cell = [tableView dequeueReusableCellWithIdentifier:cellId]; if (cell == nil) { cell = [[TableViewCellResults alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellId]; } // 设置目标进度,比如55%就是0.55 cell.targetProgress = 0.55; return cell; }
关键注意点
- 始终记住UIProgressView的
value必须在0.0-1.0之间,不要直接用百分比数字。 - 动画必须在Cell已经加入视图层级后执行,否则不会生效。
- 处理Cell复用:一定要在动画前重置进度条的初始值,不然复用的Cell会显示之前的进度状态。
内容的提问来源于stack exchange,提问作者Jon
相关产品推荐
相关产品推荐

