动画自定义UITableView节标题视图

4
在我的应用程序中,我有一个位于场景内的UITableView,其宽度会动态变化。当宽度改变时,我会对场景进行扩展动画-包括UITableViewUITableView包含自定义视图的段头,其中包含一个锚定在视图右侧的UILabel
当我的场景宽度更改时,我像这样对表格进行调整大小的动画:
[UIView animateWithDuration:0.22
                      delay:0.02
                    options:UIViewAnimationOptionCurveLinear
                 animations:^
 {
     //Change width to 320 from 220
     [menuTable setFrame:CGRectMake(menuTable.frame.origin.x, menuTable.frame.origin.y, 320, menuTable.frame.size.height)];
 }
                 completion:^(BOOL finished)
 {

 }];

这个方法可以平滑地动画调整表格大小,但是部分标题内的标签会瞬间跳到最终位置而不是动画过渡。

我尝试过调用reloadData,但效果相同,没有动画。我还尝试过调用beginUpdatesendUpdates,但也没有效果。

我应该尝试什么其他方法?


你正在使用自动布局吗? - rdelmar
UILabel不会动画显示文本更改。如果您为标签设置背景颜色,则应正确地看到标签框架进行动画处理,而文本则等待然后跳到其位置。您需要一个UILabel的子类来完全控制文本如何动画显示到其位置。 - Ryan Poolos
@rdelmar - 我正在使用自动布局。 - BreadicalMD
@RyanPoolos - 如果我按照你说的在标签上设置背景颜色,我可以看到它确实会立刻显示出来 - 标签本身并没有以任何方式进行动画处理。 - BreadicalMD
1个回答

1
在我的标签扩展实验中,我发现Ryan Poolos在他的评论中说的是正确的——即使标签通过动画进行扩展,文本也会跳到其新位置(我已将文本设置为居中对齐)。所以,我发现唯一可行的方法是使用计时器,如下所示:
-(IBAction)expandLabel:(id)sender {

    [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:@selector(expand:) userInfo:nil repeats:YES];
}

-(void)expand:(NSTimer *) aTimer {
    self.widthCon.constant += 1;
    if (self.widthCon.constant >= 200) [aTimer invalidate];
}

widthCon是我放在标签上的宽度约束的IBOutlet。如果您正在使用自动布局,应通过更改约束而不是更改框架来进行任何动画。我尚未尝试过在部分标题中使用标签,但我认为如果您使用此方法动画表格的宽度,并且标签的约束设置为以这样的方式跟随表格的扩展,则会起作用。

编辑后:

经过更多实验,看起来计时器方法是使其适用于移动标签(而不是扩展标签)的唯一方法。在这种情况下,宽度约束将是表格视图本身。

第二次编辑后:

更多实验。我发现问题是调用layoutSubviews(不应直接调用)而不是layoutIfNeeded。因此,您可以使标签位置在没有定时器的情况下进行动画处理。以下是我用于制作标题并在单击按钮时进行扩展的代码:

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UITableViewHeaderFooterView *view = [[UITableViewHeaderFooterView alloc] init];
    view.tintColor = [UIColor yellowColor];
    UILabel *label = [[UILabel alloc] init];
    [label setTranslatesAutoresizingMaskIntoConstraints:NO];
    label.backgroundColor = [UIColor redColor];
    label.text = @"Test";
    [view.contentView addSubview:label];
    [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[label]-|" options:0 metrics:nil views:@{@"label":label}]];
    [view addConstraint:[NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    return view;
}

-(IBAction)expandTable:(id)sender {
    self.widthCon.constant = 300;
    [UIView animateWithDuration:1 animations:^{
        [self.view layoutIfNeeded];
    }];
}

我实际上并没有改变标签的宽度,只是它的位置。因此,也许Ryan Poolos所说的对于宽度的更改是正确的,但对于位置的更改,至少在这种情况下,那不是问题。手动移动标签框架可能会使用计时器来解决,但这很混乱。我希望这是最后的选择 - 在我看来,应该有一种方法来指示节标题视图应该如何进行动画? - BreadicalMD
@BreadicalMD,好的,抱歉,我误解了你的问题。但是我的建议仍然是使用约束来进行动画--如果使用约束来动画表格的宽度变化,标签的位置应该会正确跟随。我会更新我的答案以反映这一点。 - rdelmar
那也不起作用 :( 不幸的是,尝试这样做会停止表格本身的动画 - 它的宽度现在会立即改变而不是动画。 self.tableWidth.constant = 320; [UIView animateWithDuration:0.22 delay:0.02 options:UIViewAnimationOptionCurveLinear animations:^ { [menuTable layoutSubviews]; [self.view layoutSubviews]; } completion:^(BOOL finished) { }]; - BreadicalMD
@BreadicalMD,是的,我也测试了一下,标签没有正确地进行动画 - 我仍在寻找解决方法。但对于我来说,表视图及其标题视图确实可以正确地进行动画,所以我不确定为什么你的不能。 - rdelmar
@BreadicalMD,是的,我也得出了同样的结论。在WWDC 2012的一个关于约束的视频中有讨论这个问题。 - rdelmar
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接