iOS UILabel 未重绘到新尺寸

发布于 2024-11-30 18:12:38 字数 2159 浏览 0 评论 0原文

我有一组 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

I have a set of UILabels that are shown in the cells of a TableView. When the user touches the cell, the label expands to show all the text I've put in there instead of a two-line truncated version.

The animation and expanding works, but when I press the label again to make it shrink the TableViewCell the label is in resizes correctly, but the label does not. I've NSLog'ed the size of the label, and programmatically my code works but it is failing to draw correctly.

Here is my cellForRowAtIndexPath method:

- (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;
}

Can anybody tell me what is going on here, because I am struggling to understand it.

Thanks in advance! :D

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

紫轩蝶泪 2024-12-07 18:12:38

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

通常的模式是回收电池,并且仅在无法回收电池时才创建新电池。使用这种方法,您确实需要(根据您的评论)某种方式来跟踪标签。 (下面的代码片段显示了执行此操作的一种方法。)

您尚未发布 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;
}

The code you have posted doesn't appear (as per your comment) to layer new labels over old ones. It does, however, mint a brand new cell each time the method is called. That's not the usual design pattern.

The usual pattern is to recycle cells and only create new ones if a recycled one is not available. Using this approach you do need (as per your comment) some way of keeping track of the label. (One way of doing this is shown in the snippet below.)

You have not posted your tableView:heightForRowAtIndexPath: method. Depending what is going on there, you might get odd behaviour, i.e. if the row height doesn't match the label height. It's also not clear when you are calling reloadData (or one the related methods) on the tableView. This does need to get called so iOS can refresh the cell row height. Maybe that's all OK in your code - but definitely worth checking.

I've tested the following code and it expands and reduces cells in the way I think you are trying to achieve in your question. For my convenience, this code just test to see if row matches a given number to determine whether it is expanded or not. You'll substitute [expandedIndexPathsArray containsObject:indexPath] for my ([indexPath row] == _pgSpecialRow).

I've separated the work out by adding two additional methods (although there is less code here altogether). This is partly to aid readability, and partly because the tableView:heightForRowAtIndexPath: methods needs to do the same sums as the tableView:cellForRowAtIndexPath: method

- (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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文