在 UITableViewCell 内动画 UILabel 文本更改
Posted
技术标签:
【中文标题】在 UITableViewCell 内动画 UILabel 文本更改【英文标题】:Animate UILabel text change inside UITableViewCell 【发布时间】:2014-06-04 01:00:12 【问题描述】:当文本属性更改时,我想在自定义UITableViewCell
中为UILabel
设置动画。
我的动画工作正常,除了每次滚动时单元格进入视野时动画都会触发,并且在调用[myTableView reloadData]
时也会触发。
使用简单的东西
if (![myLabel.text isEqualToString:newText])
// change myLabel.text with animation here.
不起作用。
我明白为什么会这样。
如果我每次都创建一个新单元格,我可以检查myLabel.text
是否有一个字符串,如果有,它是否不同,然后应用更改。但是,有时要显示的单元格太多。
重用单元格时,myLabel.text
几乎总是已经有一个字符串,并且几乎总是与我想要设置的不同。所以上述检查将不起作用。无论如何,它们都会导致动画触发。
我能想到的唯一方法是使用myLabel.text
中的最后一个已知值创建一个数组并进行比较,但这个列表会很大!
我不知道从哪里开始解决这个问题。
我想要的只是myLabel
在text
属性更改时在我的子类UITableViewCell
中做一个小翻转/背景颜色动画。我找到的最接近的解决方案将导致 tableviewcell 中的 all 标签运行动画。
我也不能在给它一个字符串之前检查myLabel.text
,因为它总是被重复使用。
我开始觉得这是做不到的。
【问题讨论】:
这是UITableViewCell
的子类吗?
是的。我应该在我的问题中提到这一点吗?
是的,应该说清楚。
好的,已修复。谢谢。
在不知道您到底想看到什么的情况下,很难说您应该做什么。例如,如果您将一个新项目插入到您的数组中(在中间某处),您是否希望该标签下方的所有标签都进行动画处理,因为数据正在移动到新单元格(再往下),或者只为您要添加的单元格?我认为解决方案将只涉及更新更改的单元格(使用 reloadRowsAtIndexPaths),而不是使用 reloadData 更新整个表。
【参考方案1】:
如果您继承了UITableViewCell
,您可以覆盖默认的prepareForReuse
方法。在此方法中,将标签的 text 属性设置为 nil
。
- (void)prepareForReuse
[super prepareForReuse];
myLabel.text = nil;
现在:
if (myLabel.text && ![myLabel.text isEqualToString:newText])
// change myLabel.text with animation here.
现在,只有在将文本从一个文本更改为新文本时,该文本才应该具有动画效果。
prepareForReuse
由 tableview 的 dequeueReusableCell
方法在单元格上调用。
【讨论】:
感谢您抽出宝贵的时间来回答,但是,这并不像我想要的那样工作。当我调用 [tableView reloadData] 时,动画不起作用。这很重要,因为我可以重新加载 UILabel 的唯一方法是通过更新 tableview,并且每次发生这种情况时标签都设置为 nil。 实际上可能有。【参考方案2】:#pragma mark - Timer Function
-(void)callAfteroneSecond_deals
NSArray *indexes = [self.tbl_deals indexPathsForVisibleRows];
MYTableViewCell *cell = (MYTableViewCell *)[_tbl_deals cellForRowAtIndexPath:index];
cell.lbl_expiredtime.text=@"Hello";
[cell.contentView bringSubviewToFront:cell.lbl_expiredtime];
【讨论】:
【参考方案3】:我会像这样在自定义单元格上定义一个方法:
- (void) updateMyLabel: (NSString *)newText
// If the new value is different than what is already set,
// and the label isn't nil, then trigger the animation
if (self.myLabel.text && self.myLabel.text != newText)
[UIView animateWithDuration...];
self.myLabel.text = newText;
然后在 tableView 的 cellForRowAtIndexPath 中调用该方法。棘手的是,当用户滚动或数据更改时(即每次调用 reloadData),cellForRowAtIndexPath 可能会被多次调用。
【讨论】:
这个我试过了。滚动时,单元格会被重复使用,并且几乎总是会初始化 myLabel 并在其重复使用的单元格的 text 属性中保存一些字符串。所以这个 if 语句,总是会返回 yes。 嗯,好的,那么正如 nhgrif 提到的,您只需在自定义单元格类的 prepareForReuse 中将标签文本设置为 nil。 是的,但是每次调用 [tableView reloadData] 或滚动视图时,所有 myLabel.text 属性都设置为 nil。这意味着上面的 if 语句将始终返回 NO。并且不会触发任何动画。【参考方案4】:我设法通过跟踪 myLabel.text
中保存的先前值来使其工作。
我在名为 previousStrings
的 viewController 上创建了一个 NSMutableDictionary
。每个键都是indexPath.row
,每个值都是该行的字典。
这是来自cellForRow
方法内部的一些代码。
NSMutableDictionary *strings;
// check to see if previousStrings already has a dictionary at key of indexPath.row
// if not, then create one.
if (![_previousStrings objectForKey:[NSString stringWithFormat:@"%d", indexPath.row]])
strings = [[NSMutableDictionary alloc] init];
else
strings = [_previousStrings objectForKey:[NSString stringWithFormat:@"%d", indexPath.row]];
那就换myLabel.text
NSString *cellText = newTextString;
// If the new string is equal to the old string, just set the label without animation
// otherwise run animation and update the value inside the strings dictionary.
if ([strings[@"myLabel"] isEqualToString:newTextString])
cell.myLabel.text = newTextString;
else
[cell.myLabel runTextChangeAnimationWithString:newTextString];
[strings setObject:newTextString forKey:@"myLabel"];
毕竟,在cellForRow
的末尾一定要把字符串字典放回previousStrings
[_previousStrings setObject:strings forKey:[NSString stringWithFormat:@"%d", indexPath.row]];
我希望这对于遇到同样问题的其他人来说是有意义的。 如果不够清楚,请随时编辑并提出问题。
这就是字典的结构。数字是每个单元格的 indexPaths。
【讨论】:
以上是关于在 UITableViewCell 内动画 UILabel 文本更改的主要内容,如果未能解决你的问题,请参考以下文章
如何最好地为 UITableViewCell 或 UIButton 设置动画以重复亮起红色
UItableviewcell中的多行UIlabel使用Autolayout