首次出现时无法在 UITableViewCell 中更改 UILabel 的框架(使用自动布局)

Posted

技术标签:

【中文标题】首次出现时无法在 UITableViewCell 中更改 UILabel 的框架(使用自动布局)【英文标题】:Cannot change frame of a UILabel in a UITableViewCell when first appearing (using Autolayout) 【发布时间】:2014-01-08 12:51:24 【问题描述】:

我的UITableView 中有一个原型单元格,其中包含一个UILabel。我想根据标签中文本的大小动态更改标签(和单元格)的大小。

我在cellForRowAtIndexPath 中创建原型单元格,如下所示:

static NSString *CellIdentifier = @"ProgramDetailCell";
ProgramDetailCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.descriptionLabel.text = self.program.subtitle;
return cell;

那么我的ProgramDetailCell有如下实现:

@implementation ProgramDetailCell
- (void)layoutSubviews 
    [super layoutSubviews];
    [self.descriptionLabel sizeToFit];

@end

第一次显示单元格时,会调用layoutSubviews,但不会调整descriptionLabel 的大小。但是,如果我向下滚动表格并再次备份,则会出现“重用”单元格,并且标签的大小已正确调整!

为什么第一次显示单元格时它不起作用 - 我需要做些什么来修复它。

提前致谢!

【问题讨论】:

你找到解决这个问题的方法了吗? 找到解决这个问题的办法了吗? 【参考方案1】:

在 xib 中,转到第一个选项卡,在 Interface Builder Document 下,取消选中使用自动布局框。

【讨论】:

这已经解决了这个问题,但现在我不能使用 AutoLayout。出路是什么? 好吧,你是对的。但是我需要在自定义 UITableViewCell 上使用自动布局,如何使用? 如果你想使用自动布局,这里重要的是约束。那么你不应该改变框架。请阅读此developer.apple.com/library/ios/documentation/UserExperience/…【参考方案2】:

它不起作用,因为您使用的是auto layout。你需要一些auto layout 方法来实现这一点。

这是解决方案。

第 1 步:

UILabel 固定在UITableViewCell 的顶部和底部。您可以通过Interface Builder 实现此目的,方法是在单元格的UILabel 上设置Vertical Constrainttopbottom。如果单元格的高度增加,这将使UILabel 的高度增加,反之亦然。

第 2 步:

在你的 UIViewController 中 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 方法计算 UITableViewCell 的大小。

您可以使用:

 CGRect textFrame = [YourText boundingRectWithSize:CGSizeMake(width of the label, FLT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@NSFontAttributeName:Your Font context:nil];

现在返回textFrame.size.height + 填充(如果存在)。

第 3 步:

在第一次编译和运行之后,您将实现您想要的 --- “根据标签中文本的大小动态更改标签(和单元格)的大小”。

【讨论】:

第一个解决方案肯定对我有用。谢谢!【参考方案3】:

从服务器检索所有数据后,您可以使用此方法获得UILabel 的高度。

CGSize maximumSize = CGSizeMake(210, 9999);
for (int i = 0; i < [_arrProductList count]; i++) 

      float row_height = 0.0f;

      ProductInformation *product_obj = [_arrProductList objectAtIndex:i];
      CGSize desc_size = [self measureHeightForText:product_obj.product_desc forFont:   [UIFont systemFontOfSize:14] forSize:maximumSize];

      row_height = row_height + desc_size.height;

   //   [_arrRowHeights addObject:[NSString stringWithFormat:@"%f", row_height]]; You can take it into array.



[tableView reloadData];

这里我给出了measureHeightForText: 的描述。此逻辑适用于所有iOS5,iOS6,iOS7

-(CGSize)measureHeightForText:(NSString *)strText forFont:(UIFont *)font forSize:(CGSize)size

    if (!testingLabel) 

        testingLabel = [[UILabel alloc] init];
        // testingLabel.font = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
        testingLabel.text = @"";
        testingLabel.numberOfLines = 0;

    

    testingLabel.text =strText;
    testingLabel.font = font;
    CGSize expectedSize = [testingLabel sizeThatFits:size];
    return expectedSize;

然后根据它更新标签的大小。这对我来说很好。我正在使用它。

【讨论】:

在 UITableView 委托调用之外更改标签的框架没有任何区别。你也在使用自动布局吗?【参考方案4】:

因为当layoutSubviews 被调用时,您的descriptionLabel 的文本尚未设置。当你滚动时,文本被设置。所以现在是正确的。

我建议你在设置文本后拨打sizeToFit

static NSString *CellIdentifier = @"ProgramDetailCell";
ProgramDetailCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.descriptionLabel.text = self.program.subtitle;
[cell.descriptionLabel sizeToFit];
return cell;

【讨论】:

【参考方案5】:

heightForRowAtIndexPath 中调用它并手动计算高度

static NSString *CellIdentifier = @"ProgramDetailCell";
ProgramDetailCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.descriptionLabel.text = self.program.subtitle;
[cell.descriptionLabel sizeToFit];

return cell.descriptionLabel.frame.size.height+cell.descriptionLabel.frame.origin.y;

【讨论】:

谢谢,但这只会改变单元格的大小,而不是第一次显示标签时的大小。 是的,在 cellForRowAtIndexPath 中做同样的事情并返回单元格而不是高度 这也不起作用。标签第一次出现时,它会保留界面生成器的原始大小。【参考方案6】:

您可以使用以下代码:

//Calculate the expected size based on the font and linebreak mode of your label
// FLT_MAX here simply means no constraint in height
CGSize maximumLabelSize = CGSizeMake(296, FLT_MAX);

CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font constrainedToSize:maximumLabelSize lineBreakMode:yourLabel.lineBreakMode];   

//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;

【讨论】:

我应该把这段代码放在哪里? cellForRowAtIndexPath? UITableViewCell 内的 layoutSubviews? cellForRowAtIndexPath 谢谢,但这没有用。框架的大小与首次出现时在 IB 中的大小相同,只有在滚动后重新显示单元格时才会更改为新大小。 我认为在标签上设置文字之前你已经写好了尺寸代码,你需要最后在标签上设置文字【参考方案7】:

如果您的要求是动态更改标签高度,请点击以下链接。当我们需要改变标签的高度时,我们也需要改变行高:

Resizing UILabel not quite working

【讨论】:

我试过了,但没有帮助。你也在使用自动布局吗? 不,我没有使用自动布局。我为完整的应用程序编写了代码,没有使用 Xib 和 Storyboard。【参考方案8】:

使用下面的代码在单元格中设置动态高度

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath


    NSString *messagetext=[NSString stringWithFormat:@"%@",[[arryStoryView objectAtIndex:indexPath.row] valueForKey:@"messagetext"]];

    CGSize StoryTextSize= [messagetext sizeWithFont:[UIFont fontWithName:@"Georgia" size:17.0f] constrainedToSize:CGSizeMake(300, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];

    int TotalHeight;
    TotalHeight= StoryTextSize.height + 10; 

    return TotalHeight;



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


    static NSString *CellIdentifier = @"Cell1";
    UITableViewCell *cell=[tblSendMsg dequeueReusableCellWithIdentifier:CellIdentifier];

    cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
                                 reuseIdentifier:CellIdentifier];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    NSString *storytext=[NSString stringWithFormat:@"%@",[[arryStoryView objectAtIndex:indexPath.row] valueForKey:@"storytext"]];

    CGSize StoryTextSize = [storytext sizeWithFont:[UIFont fontWithName:@"Georgia" size:17.0f] constrainedToSize:CGSizeMake(300, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
    lblStoryText.frame=CGRectMake(5, 25, [[UIScreen mainScreen] bounds].size.width-10, StoryTextSize.height+30);

    int nooflines=StoryTextSize.height/16;
    int i= StoryTextSize.height;
    if(i%16 !=0)
    
        nooflines=nooflines+1;
    

    lblStoryText.numberOfLines=nooflines;
    lblStoryText.font=[UIFont fontWithName:@"Georgia" size:17.0f];
    lblStoryText.text=[NSString stringWithFormat:@"%@",storytext];

    return cell;

【讨论】:

这对我不起作用。你在使用自动布局吗?【参考方案9】:

如果您使用自动布局,修改框架将无效。

相反,您应该修改约束。

【讨论】:

以上是关于首次出现时无法在 UITableViewCell 中更改 UILabel 的框架(使用自动布局)的主要内容,如果未能解决你的问题,请参考以下文章

首次加载 UITableViewController 时自定义 UITableViewCell 无法正确显示

UITableViewCell 上的圆形 UIImageView 在首次加载时不起作用

UITableViewCell 中的 UITextView 在 `textViewDidBeginEditing` 方法中首次分配失败

UIView 动画在 UITableViewCell 内无法正常工作

重新排序时无法从当前位置拖动 UITableViewCell

在 UiTableViewCell 上设置时,DisclosureButton Indicator 或任何类型的附件类型似乎都没有出现