【问题标题】:UITableViewCell subview not being displayed when the table is first displayed首次显示表格时未显示 UITableViewCell 子视图
【发布时间】:2012-07-23 01:44:20
【问题描述】:

我正在尝试向我的表格单元格添加删除线标签(以 BOOL hasStrikethrough 为条件)。问题是第一次显示表格时没有出现删除线(即使 hasStrikethrough == YES)。如果滚动表格,则行会重新显示,并且删除线会正确显示。删除线只是作为 UITableViewCell 的子视图添加的 UILabel。

这是我的 cellForRowAtIndexPath 代码:

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

static NSString *CellIdentifier = @"ItemCell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell==nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}


Item  *item = [self.fetchedResultsController objectAtIndexPath:indexPath];

cell.textLabel.text = item.itemName;
cell.textLabel.textAlignment = UITextAlignmentLeft;
cell.showsReorderControl = YES;
cell.shouldIndentWhileEditing = NO;

if ([[item hasStrikethrough] boolValue] == YES) {
    [self addStrikethrough:cell];
}

return cell;
}

addStrikethrough 的代码如下:

- (void)addStrikethrough:(UITableViewCell*)cell
{
CGRect frame = cell.textLabel.frame;
UILabel *strikethrough = [[UILabel alloc] initWithFrame:frame];
strikethrough.opaque = YES;
strikethrough.backgroundColor = [UIColor clearColor];
strikethrough.text = @"------------------------------------------------";
strikethrough.lineBreakMode = UILineBreakModeClip;
[cell addSubview:strikethrough];
}

提前致谢:-)

【问题讨论】:

    标签: ios uitableview subview addsubview


    【解决方案1】:

    问题在于CGRect frame = cell.textLabel.frame;这一行
    单元格的 textLabel 尚未布局,因此框架将为 (0,0,0,0) 并且您不会看到删除线标签。

    您在下一个单元格中看到删除线的原因是因为那些是已经布置 textLabel 的重用单元格。

    在我看来,你有两个选择:
    第一个选项,自己设置删除线框,你可以使用 sizeWithFont 来确定需要的宽度,字体应该是 textFiled 字体。稍微玩一下,找到正确的 x 偏移量,这样它就会完全在 textLabel 上。

    - (void)addStrikethrough:(UITableViewCell*)cell
    {
        CGSize textLabelSize = [cell.textLabel.text sizeWithFont:[UIFont systemFontOfSize:20.0]];
    
        CGFloat cellHeight = cell.bounds.size.height;
        CGFloat strikethroughLabelHeight = 20.0;
    
        CGRect frame = CGRectMake(12, (cellHeight - strikethroughLabelHeight)/2, textLabelSize.width, strikethroughLabelHeight);
        UILabel *strikethrough = [[UILabel alloc] initWithFrame:frame];
        strikethrough.opaque = YES;
        strikethrough.backgroundColor = [UIColor clearColor];
        strikethrough.text = @"------------------------------------------------";
        strikethrough.lineBreakMode = UILineBreakModeClip;
        [cell.contentView addSubview:strikethrough];
    }  
    

    第二个选项是继承 UITableViewCell 并为其添加删除线标签。
    然后你可以在 layoutSubviews 方法中设置它的框架,你可以根据你的需要隐藏/取消隐藏这个标签...

    【讨论】:

    • 就是这样。今天有机会实施和测试。这已经解决了。非常感谢。
    【解决方案2】:

    根据其重用标识符重用单元格。目前您只使用一个标识符,因此“没有子视图的单元格”在操作系统看来与“有子视图的单元格”相同。

    尝试在开头检查删除线条件,并在这种情况下发明一个新的重用标识符(例如StrikeIdentifier)。

    这是我建议的一种方法:

    Item *item = [self.fetchedResultsController objectAtIndexPath:indexPath];
    BOOL isStrike = ([[item hasStrikethrough] boolValue]);
    
    static NSString *CellIdentifier = @"ItemCell";
    static NSString *StrikeIdentifier = @"ItemCellStrike";
    
    UITableViewCell *cell = (isStrike)
                            ? [tableView dequeueReusableCellWithIdentifier:StrikeIdentifier]
                            : [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    if (cell==nil) {
        if (isStrike) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:StrikeIdentifier];
            [self addStrikethrough:cell];
        } else {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }
    }
    
    . . .
    

    【讨论】:

    • 首先我在 cellForRowAtIndexPath: 中尝试过这个。我已从 addStrikethrough: 中获取代码并将其放在添加到 if(cell==nil) 的 else 语句中。我已将 else 语句中的 cell.textLabel.text 硬编码为等于“DEQUEUED CELL”。我注释掉了对 addStrikethrough: 的条件调用。当你跑步时。该表显示带有文本“DEQUEUED CELL”但没有删除线的行?所以每一行都是一个出列的单元格,每一行都没有显示删除线?每个单元格都应该添加子视图。没有创建新的单元格,因此不应出现标识符混淆。
    • 我在答案中添加了一个代码示例,试图说明我的意思。您需要模板单元具有显示其数据所需的一切,因为操作系统不会每次都要求您创建它。
    • 嗨凯文,非常感谢你看这个。我已经实现了您提供的代码,但不幸的是它对我不起作用。我还将 isStrike 硬编码为 YES 以排除我的核心数据错误。同样,当我运行时,单元格显示时没有删除线。我已经逐步确保 addStrikethrough: 被调用。即使我滚动行,删除线也不会出现(使用我的代码)。
    • 您所做的看起来与我之前制作的表格相似...一个区别是我的单元格具有自定义背景视图,我在其中设置了自动调整大小的蒙版,例如newView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight;cell.backgroundView = newView;。我不确定这个细节是否重要。
    猜你喜欢
    • 2015-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多