ios - 使用自动布局在运行时将 subview 添加到使用 xib 配置的 UITableviewCell

标签 ios objective-c uitableview autolayout

有一个 UITableview 子类,它有 *.xib 文件,其中配置了自动布局(如下图所示,在 xib 中,所有依赖项都配置为 2 标签样式)。这个单元格可以像通常的自动布局单元格一样动态计算它的高度。

但有一种情况,根据接收到的数据,标签的数量可能会有所不同 - 取决于模型中的数据。

enter image description here

有没有办法使用现有的自动布局系统将多个标签 (3,5,n) 作为 subview 添加到单元格?这很重要,因为细胞不应该失去 self 计算其大小的能力

最佳答案

由于您使用的是 .xibs(出于多种原因非常好),最安全、最简单且性能最高的方法是使用不同的结果标识符注册您的 .xib。最好扫描您的模型以找出并注册您需要的模型(注册太多会出错;反之则会出错并立即崩溃)。在子类中,覆盖 -initWithStyle:reuseIdentifier: 并在那里进行设置。

有几种方法可以进行设置。

  1. IB heavy:创建一个标签数量最多的单元格。将它们彼此附加,并使用单独的约束将每个附加到单元格内容 View 的底部,并将约束按优先级排序,1000 是附加到底部的标签,没有被删除,优先级从那里下降。然后在 -initWithStyle:reuseIdentifier:; 中去掉你不需要的标签;它们的约束将被移除,允许下一个最低优先级生效。
  2. 循环:对于任意数字,您可以在 -initWithStyle:reuseIdentifier: 中添加标签及其约束 - 循环的重用标识符可以是 +stringWithFormat number,它可以让您使用 -intValue 获取数字。但这可能过于简单,因此您可能想尝试创建方法 -formatWithNumberOfLabels 并检查 -didSetup 标志。

编辑:选项 2 比我预期的要麻烦得多。此示例是程序化的,但您应该能够看到如何针对 .xibs 调整它。在单元格的实现中:

-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (self) {
        [self.contentView setTranslatesAutoresizingMaskIntoConstraints:NO];

        NSMutableDictionary *layoutDictionary = [[NSMutableDictionary alloc] init];
        NSMutableString *visualFormatLanguageString = [[NSMutableString alloc] init];

        NSInteger numberOfLabels = reuseIdentifier.integerValue; //This is not that safe, using below class method is the only way to make it safe to do this.

        for (int i = 0; i <= numberOfLabels; i++) {
            if (i == 0) {
                [visualFormatLanguageString appendString:@"V:|-20-"];
            } else {
                [visualFormatLanguageString appendString:@"-8-"];
            }

            UILabel *labelX = [[UILabel alloc] init];
            [labelX setTranslatesAutoresizingMaskIntoConstraints:NO];

            int tag = 1000 + i;
            labelX.tag = tag;

            NSString *labelXString = [NSString stringWithFormat:@"Label%i", tag];
            [layoutDictionary setObject:labelX forKey:labelXString];
            [visualFormatLanguageString appendString:[NSString stringWithFormat:@"[%@]", labelXString]];

            [self.contentView addSubview:labelX];
        }
        [visualFormatLanguageString appendString:@"-20-|"];
        [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualFormatLanguageString
                                                                       options:NSLayoutFormatAlignAllLeading
                                                                       metrics:nil
                                                                         views:layoutDictionary]];
    }
    return self;
}

+ (NSString*)reuseStringForNumber:(NSInteger)reuseNumber {
    return [NSString stringWithFormat:@"%li",(long) reuseNumber];
}

在 TableView 数据源中,您必须 -- 对于您认为需要的最大标签数 - 注册:

- (void)viewDidLoad {
    [super viewDidLoad];

    for (NSInteger i = 0; i < 4; i++) {
        [self.tableView registerClass:[MultiLabelTableViewCell class] forCellReuseIdentifier:[MultiLabelTableViewCell reuseStringForNumber:i]];
    }

    self.tableView.estimatedRowHeight = 44;
}

对于创建标签数量(行 % 4)+ 1 的示例:

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

    NSInteger cellNumber = indexPath.row % 4;

    MultiLabelTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[MultiLabelTableViewCell reuseStringForNumber:cellNumber] forIndexPath:indexPath];

    for (int i = 0; i <= cellNumber; i++) {
        int tag = 1000 + i;
        [(UILabel *)[cell.contentView viewWithTag:tag] setText:[NSString stringWithFormat:@"Cell %i, label %i", indexPath.row, i]];
    }

    return cell;
}

然后只需在单元格中为索引路径的行调用您需要的 reuseIdentifier,您和系统都必须做最少的工作才能为您的单元格获得正确的高度和布局。

关于ios - 使用自动布局在运行时将 subview 添加到使用 xib 配置的 UITableviewCell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28622524/

相关文章:

ios - 收到通知时点击打开本地通知 - iOS - Swift

iphone - ios中的多个webview

ios - 复制 block

iOS:从辅助 View 启动导航 Controller

ios - 单击按钮弹出 UIPickerView (Swift)

ios - 隐藏导航栏后面的第一个单元格

ios - CATextLayer 文本颜色始终为黑色

iphone - 更改 UITabBarController 更多项目颜色

ios - Adobe Air IOS 游戏无法在 IOS8 中运行

iphone - 在 iOS 6 中将带有 CALayer.mask 的 UIView 保存为 UIImage