【问题标题】:iOS UILabel not redrawing to a new sizeiOS UILabel 未重绘为新大小
【发布时间】:2011-08-21 01:43:10
【问题描述】:

我有一组 UILabel,它们显示在 TableView 的单元格中。当用户触摸单元格时,标签会展开以显示我放入其中的所有文本,而不是截断的两行版本。

动画和扩展有效,但是当我再次按下标签以使其缩小 TableViewCell 时,标签正确调整大小,但标签没有。我已经对标签的大小进行了 NSLog,并且以编程方式我的代码可以正常工作,但无法正确绘制。

这是我的 cellForRowAtIndexPath 方法:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray *sectionContents = [[self tableData] objectAtIndex:[indexPath section]];
    NSString *contentForRow = [sectionContents objectAtIndex:[indexPath row]];

    UILabel *label = nil;
    int noOfLines;

    UITableViewCell *cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"];
    label = [[UILabel alloc] initWithFrame:CGRectZero];

    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);

    label.text = contentForRow;
    if ([expandedIndexPathsArray containsObject:indexPath])
        {
        noOfLines = 0;
        CGSize size = [contentForRow sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
        label.frame = CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f));
        NSLog(@"height is now %f",label.frame.size.height);
    } else {
        noOfLines = 2;
        CGSize size = [contentForRow sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
        label.frame = CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MIN(size.height, 44.0f));
         NSLog(@"height is now %f",label.frame.size.height);
    }
    NSLog(@"Number of Lines: %d",noOfLines);
    label.lineBreakMode = UILineBreakModeWordWrap;
    label.backgroundColor = [UIColor blueColor];
    label.font = [UIFont systemFontOfSize:FONT_SIZE];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    label.numberOfLines = noOfLines;
    [[cell contentView] addSubview:label];
    [label release];
    return cell;
}

谁能告诉我这里发生了什么,因为我很难理解它。

提前致谢! :D

【问题讨论】:

  • 好的,我发现我的 cellForRowAtIndexPath 实际上是在旧标签上叠加新标签,而不是先删除它们。我是否需要以某种方式编辑已经存在的标签,还是删除它的子视图并添加一个新的?这会发生在 cellForRowAtIndexPath 还是 didSelectRowAtIndexPath 中?

标签: iphone objective-c ios uitableview uilabel


【解决方案1】:

您发布的代码不会出现(根据您的评论)以将新标签叠加在旧标签上。但是,每次调用该方法时,它都会创建一个全新的单元格。这不是通常的设计模式。

通常的模式是回收电池,并且仅在没有回收的电池可用时才创建新电池。使用这种方法,您确实需要(根据您的评论)某种方式来跟踪标签。 (一种方法如下面的 sn-p 所示。)

你还没有发布你的 tableView:heightForRowAtIndexPath: 方法。根据那里发生的情况,您可能会遇到奇怪的行为,即如果行高与标签高度不匹配。当您在 tableView 上调用 reloadData (或相关方法之一)时也不清楚。这确实需要调用,以便 iOS 可以刷新单元格行高。也许在您的代码中一切正常 - 但绝对值得检查。

我已经测试了以下代码,它以我认为您试图在您的问题中实现的方式扩展和减少单元格。为方便起见,此代码仅测试行是否与给定数字匹配以确定它是否被扩展。您将 [expandedIndexPathsArray containsObject:indexPath] 替换为我的 ([indexPath row] == _pgSpecialRow)。

我通过添加两个额外的方法将工作分开(尽管这里的代码更少)。这部分是为了提高可读性,部分是因为 tableView:heightForRowAtIndexPath: 方法需要与 tableView:cellForRowAtIndexPath: 方法进行相同的求和

- (UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString* cellIdentifier = @"Cell";

    // see if there's a cell available to recylce
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (!cell)
    {
        // there's no cell to recycle, so make a new one
        // add a label to it and tag the label so we can find it later

        cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier];
        UILabel* label = [[UILabel alloc] init];

        // do set up on label that doesn't vary with cell content
        [label setTag: 101];
        label.lineBreakMode = UILineBreakModeWordWrap;
        label.backgroundColor = [UIColor blueColor];
        label.font = [UIFont systemFontOfSize:FONT_SIZE];

        [[cell contentView] addSubview:label];
        [label release];
    }

    // either on a recycled cell or on the cell just created, set the contents

    NSArray *sectionContents = [[self tableData] objectAtIndex:[indexPath section]];
    NSString *contentForRow = [sectionContents objectAtIndex:[indexPath row]];
    UILabel* label = (UILabel*)[[cell contentView] viewWithTag:101];

    [self adjustLabel: label forText:contentForRow andExpanded:([indexPath row] == _pgSpecialRow)];

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;
}

- (void) adjustLabel: (UILabel*) label forText: (NSString*) text andExpanded: (BOOL) expanded;
{    
    label.text = text;

    CGFloat height = [self heightForLabelWithText: text expanded: expanded];
    label.frame = CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), height);

    label.numberOfLines = expanded ? 0: 2;
}


- (CGFloat) heightForLabelWithText: (NSString*) text expanded: (BOOL) expanded;
{
    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);

    if (expanded)
    {
        return MAX([text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap].height, 44.0);
    }

    return MIN([text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap].height, 44.0);
}


- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray *sectionContents = [[self tableData] objectAtIndex:[indexPath section]];
    NSString *contentForRow = [sectionContents objectAtIndex:[indexPath row]];

    // return a cell height that's big enough (with a bit of extra margin)
    return [self heightForLabelWithText: contentForRow expanded:([indexPath row] == _pgSpecialRow)]+ 16.0;
}

【讨论】:

  • 感谢 Matthew,您的代码非常适合我。我不得不稍微摆弄一下我的 didSelectRowAtIndexPath 方法,但它现在可以正常工作了。我不得不承认我花了几个小时来工作并理解你的代码发生了什么以及为什么,但我现在明白了。感谢您抽出时间回复!非常感激! :D
猜你喜欢
  • 2017-04-20
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 1970-01-01
  • 2010-12-04
  • 2014-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多