按单词包装 UILabel 并以编程方式扩展 UITableViewCell 高度

Posted

技术标签:

【中文标题】按单词包装 UILabel 并以编程方式扩展 UITableViewCell 高度【英文标题】:Wrap UILabel by word and expand UITableViewCell height programmatically 【发布时间】:2018-06-15 15:39:14 【问题描述】:

我以编程方式创建了布局约束,以便在表格单元格中排列 UI 组件。

以下是我正在实施的约束:

单元格的左侧部分包含nameUIView(完成) 单元格的右侧部分包含valueUIView(完成) nameUIViewvalueUIView 部分的宽度应该相等(完成) nameUIViewvalueUIView 的高度和宽度应该是可用空间的 100%(完成) nameUIView 包含一个 nameUILabel(完成) nameUILabel 应该使用单词换行(需要建议) 如果nameUILabel 中的文本过大,则 UITableViewCell 单元格的高度应扩大(需要建议)

如何以编程方式实现该布局的换行和高度扩展?

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) 
        NSString *reuseID = reuseIdentifier;

        // The view containing the label (left, red)
        UIView *nameUIView = [[UIView alloc] init];
        self.nameUIView = attributeNameView;
        [self.nameUIView setBackgroundColor:[UIColor redColor]];
        [self.nameUIView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self.contentView addSubview:self.nameUIView];

        // The label (green)
        UILabel *nameUILabel = [[UILabel alloc] init];
        self.nameUILabel = nameUILabel;
        [self.nameUILabel setTextColor:[UIColor blackColor]];
        [self.nameUILabel setBackgroundColor:[UIColor greenColor]];
        [self.nameUILabel setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self.nameUILabel setLineBreakMode:NSLineBreakByWordWrapping];
        [self.nameUIView addSubview:self.nameUILabel];

        // The view containing the value (right, blue)
        UIView *valueUIView = [[UIView alloc] init];
        self.valueUIView = valueUIView;
        [self.valueUIView setBackgroundColor:[UIColor blueColor]];
        [self.valueUIView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self.contentView addSubview:self.valueUIView];

        NSDictionary *views = NSDictionaryOfVariableBindings(nameUIView, nameUILabel, valueUIView);
        NSArray *constraints;

        // The constraint to align the views horizonzally (1:1) sizing
        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameUIView][valueUIView(==nameUIView)]|"
                                                                       options: 0
                                                                       metrics:nil
                                                                         views:views];

        [self.contentView addConstraints:constraints];

        // 100% height for name view
        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameUIView]|"
                                                              options: 0
                                                              metrics:nil
                                                                views:views];
        [self.contentView addConstraints:constraints];

        NSLayoutConstraint *constraint;

        // Center name label horizontally
        constraint = [NSLayoutConstraint constraintWithItem:nameUILabel
                                attribute:NSLayoutAttributeCenterX
                                relatedBy:NSLayoutRelationEqual
                                toItem:nameUIView
                                attribute:NSLayoutAttributeCenterX
                                multiplier:1.f constant:0.f];// Not possible via VFL
        [self.contentView addConstraint:constraint];

        // Center name label vertically
        constraint = [NSLayoutConstraint constraintWithItem:nameUILabel
                                                                      attribute:NSLayoutAttributeCenterY
                                                                      relatedBy:NSLayoutRelationEqual
                                                                         toItem:nameUIView
                                                                      attribute:NSLayoutAttributeCenterY
                                                                     multiplier:1.f constant:0.f];// Not possible via VFL
        [self.contentView addConstraint:constraint];

        // 100% height for value view
        constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[valueUIView]|"
                                                              options: 0
                                                              metrics:nil
                                                                views:views];

        [self.contentView addConstraints:constraints];

    
    return self;

【问题讨论】:

UILabel 必须有一个受限制的 宽度 才能允许换行。 @DonMag 与我在答案中使用的方法相同。如果标签超出单元格高度,如何扩展单元格高度仍然是一个问题。 您是在设置tableView.rowHeight = UITableViewAutomaticDimension 并设置tableView.estimatedRowHeight = 吗? 是的,我正在 viewWillAppear 中这样做。但是,它确实帮助我找到了解决方案。很快就会发布... 【参考方案1】:
    单词换行

添加这个额外的约束(将标签的宽度设置为父视图)确实启用了自动换行:

constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[attributeNameLabel(==attributeNameView)]|"
                                                      options: 0
                                                      metrics:nil
                                                        views:views];

        [self.contentView addConstraints:constraints];

最后,我必须将文本居中:

[self.attributeNameLabel setTextAlignment:NSTextAlignmentCenter];
    根据内容扩展单元格高度

UITableView也需要设置这些属性

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight =

将包装超级视图的高度设置为它包含的标签

constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameUIView(==nameUILabel)]|"
                                                      options: 0
                                                      metrics:nil
                                                        views:views];

[self.contentView addConstraints:constraints];

最小高度限制(可选)

constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameUIView(>=50)]|"
                                                      options: 0
                                                      metrics:nil
                                                        views:views];

[self.contentView addConstraints:constraints];

【讨论】:

以上是关于按单词包装 UILabel 并以编程方式扩展 UITableViewCell 高度的主要内容,如果未能解决你的问题,请参考以下文章

UILabel 不能可靠地包装

故事板中的子类 viewController 并以编程方式从子类更改 UI

遇到 NSLayoutConstraints 问题并以编程方式使用自动布局时,UIViews 停留在 (0,0)

如何拥有具有两种不同单元格类型的 UITableView 并以编程方式设置每个单元格布局,而不是通过情节提要?

UIAppearance 未对以编程方式创建的 UILabel 生效

以编程方式从 UITextField 接收 UILabel 值