0

我正在尝试将多行标签包装在静态内容表 tableview 中,根据需要扩展行tableView:heightForRowAtIndexPath:

作为静态表,我可以设置IBOutlets;我的标签是_instructionLabel

稍微简化一下(表中实际上有多行),它看起来像这样:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *labelText = _instructionLabel.text;
    CGFloat labelWidth = _instructionLabel.frame.size.width;
    CGSize constrainToSize = (CGSize){.width = labelWidth, .height = MAXFLOAT};
    CGSize textSize = [labelText sizeWithFont:_instructionLabel.font constrainedToSize:constrainToSize lineBreakMode: _instructionLabel.lineBreakMode];
    return textSize.height + 10;
}

(在我们继续之前:我知道UILabel可能没有画到它的全宽。我计划稍后弄清楚如何补偿它,但这不是我的问题。)

问题来了:labelWidth错了。在 iPad iOS 6 模拟器(纵向)上运行时捕获标签的屏幕截图,它的宽度约为 438 像素。我得到 638。(在 iOS 7 上,我得到 728。)

为了解决这个问题,我将这些行添加到viewWillAppear

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear: animated];

    [self.tableView setNeedsLayout];
    [self.tableView layoutIfNeeded];
    [self.tableView reloadData];
}

这会导致第二次通过表设置。现在,labelWidth更接近:482。但这与我的预期相差甚远。

我也尝试过调用 label's sizeToFit,但它似乎依赖于相同的错误数据。

我已经验证了标签的大小最终设置正确,方法是将其放入viewWillAppear

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    CGRect frame = _instructionLabel.frame;
    NSLog(@"%@", NSStringFromCGRect(frame));
    // Output: {{20, 0}, {438, 30}}
});

如何在 tableview 的最终调用之前和绘制之前确保标签的宽度设置正确?heightForRowAtIndexPath

4

1 回答 1

0

您是否尝试过在此方法中调整行高?

-(void)tableView:(UITableView*)tableView willDisplayCell:(UITableViewCell*)cell forRowAtIndexPath:(NSIndexPath) {

它是在 UITableView 的一些内部工作之后调用的,我们没有暴露它们已经运行它们的过程并稍微“调整”了你的布局。

它通常是对细胞的视觉外观进行最终调整的正确位置。不过,对及时性的相同要求也适用于此,您的代码应该非常敏捷地提供所需的信息,因此请确保您立即并且始终拥有手头所需的数据。

于 2013-10-18T19:32:33.960 回答