使用autolayout将运行时的子视图添加到使用xib配置的UITableviewCell

时间:2015-02-20 05:56:59

标签: ios objective-c uitableview autolayout

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

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

enter image description here

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

1 个答案:

答案 0 :(得分:2)

由于您使用的是.xibs(很好的原因有几个),最安全,最麻烦,性能最高的方法是使用不同的resue标识符注册.xib。最好扫描你的模型,找出并记录你需要的那些(错误的是注册太多;错误的另一种方式和即时崩溃)。在子类中,覆盖-initWithStyle:reuseIdentifier:并在那里进行设置。

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

  1. IB heavy:创建一个具有最大标签数的单元格。将它们彼此连接,并使用单独的约束将每个约束附加到单元格内容视图的底部,并将约束优先级排列,其中1000是附加到底部的标签,没有删除,优先级从那里删除。然后在-initWithStyle:reuseIdentifier:中删除您不想要的标签;他们的约束将被删除,允许次低优先级生效。
  2. 循环:对于任意数字,您可以在-initWithStyle:reuseIdentifier:中添加标签及其约束 - 对于循环编号,重用标识符可以是+stringWithFormat,这样可以使用{获取数字-intValue {1}}。这可能过于冗长,因此您可能想尝试创建方法-formatWithNumberOfLabels并检查-didSetup标志。
  3. 编辑:选项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,并且您和系统都必须执行最少的工作以获得单元格的正确高度和布局。