【问题标题】:UITableViewCell not autosizingUITableViewCell 不自动调整大小
【发布时间】:2021-07-24 00:50:25
【问题描述】:

我在 UITableViewCell 子类中有两个标签。我希望两个标签都是多行标签,所以我将它们的行数设置为零。但问题是我的表格视图单元格没有扩展。事实上,即使我将两个方向的两个标签的抗压优先级都设置为 1000,标签也会被压扁。

我已将firstLabel UILabel 属性的背景设置为橙色,将secondLabel UILabel 属性的背景设置为黄色,以便于查看标签。每行之间还有一个分隔线,以便更容易看到高度。

这是视图在设备上运行时的样子。标签全部被压缩,无论我在约束中添加多少填充或在标签中放入多少内容,行的大小都不会增加。此外,第一行中的第一个标签有足够的内容,应该不止一行,但它会被...截断。

这是我为此使用的代码。第一部分是具有两个标签的表格视图单元子类 - firstLabel(左侧)和 secondLabel(右侧)。接下来,我有包含表格视图的视图的代码,并显示了表格视图的配置方式。最后,还有一个 UITableView 子类,将 table 的 intrinsicContentSize 设置为 table 的内容大小。我添加了这个,因为没有这个表格框架总是保持为零,所以表格视图数据源方法不会被调用。如果有人也知道更好的方法来做到这一点,那将不胜感激。

UITableViewCell 子类

这是我的 UITableViewCell 的实现。它以编程方式使用,所以我是

@interface MyTableViewCell ()

@property (strong, nonatomic) UILabel *firstLabel;
@property (strong, nonatomic) UILabel *secondLabel;

@end

@implementation MyTableViewCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        [self initialize];
    }
    return self;
}

- (void)initialize {
    [self.contentView setBackgroundColor:[UIColor systemTealColor]];
    [self.backgroundView setBackgroundColor:[UIColor systemGrayColor]];
    
    [self addSubview:self.firstLabel];
    [self addSubview:self.secondLabel];
    
    NSLayoutConstraint *heightConstraint = [self.heightAnchor constraintEqualToConstant:1.0f];
    [heightConstraint setPriority:50];
    
    [NSLayoutConstraint activateConstraints:@[
        [self.firstLabel.leadingAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.leadingAnchor],
        [self.firstLabel.topAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.topAnchor],
        [self.firstLabel.trailingAnchor constraintEqualToAnchor:self.centerXAnchor constant:-4.0f],
        
        [self.secondLabel.leadingAnchor constraintEqualToAnchor:self.centerXAnchor constant:4.0f],
        [self.secondLabel.topAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.topAnchor],
        [self.secondLabel.trailingAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.trailingAnchor],
        
        [self.contentView.layoutMarginsGuide.bottomAnchor constraintGreaterThanOrEqualToAnchor:self.firstLabel.bottomAnchor constant:20.0f],
        [self.contentView.layoutMarginsGuide.bottomAnchor constraintGreaterThanOrEqualToAnchor:self.secondLabel.bottomAnchor constant:20.0f],
        
        heightConstraint
    ]];
}

- (UILabel *)firstLabel {
    if (!self->_firstLabel) {
        self->_firstLabel = [[UILabel alloc] init];
        self->_firstLabel.translatesAutoresizingMaskIntoConstraints = NO;
        self->_firstLabel.numberOfLines = 0;
        self->_firstLabel.userInteractionEnabled = NO;
        self->_firstLabel.contentMode = UIViewContentModeScaleToFill;
        [self->_firstLabel setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisHorizontal];
        [self->_firstLabel setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisVertical];
        [self->_firstLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
        [self->_firstLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
        self->_firstLabel.textAlignment = NSTextAlignmentNatural;
        self->_firstLabel.lineBreakMode = NSLineBreakByTruncatingTail;
        self->_firstLabel.baselineAdjustment = UIBaselineAdjustmentAlignBaselines;
        self->_firstLabel.adjustsFontSizeToFitWidth = NO;
        self->_firstLabel.backgroundColor = [UIColor orangeColor];
    }
    return self->_firstLabel;
}

- (UILabel *)secondLabel {
    if (!self->_secondLabel) {
        self->_secondLabel = [[UILabel alloc] init];
        self->_secondLabel.translatesAutoresizingMaskIntoConstraints = NO;
        self->_secondLabel.numberOfLines = 0;
        self->_secondLabel.userInteractionEnabled = NO;
        self->_secondLabel.contentMode = UIViewContentModeScaleToFill;
        [self->_secondLabel setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisHorizontal];
        [self->_secondLabel setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisVertical];
        [self->_secondLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
        [self->_secondLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
        self->_secondLabel.textAlignment = NSTextAlignmentNatural;
        self->_secondLabel.lineBreakMode = NSLineBreakByTruncatingTail;
        self->_secondLabel.baselineAdjustment = UIBaselineAdjustmentAlignBaselines;
        self->_secondLabel.adjustsFontSizeToFitWidth = NO;
        self->_secondLabel.backgroundColor = [UIColor yellowColor];
    }
    return self->_secondLabel;
}

- (void)setData:(MyModel *)data {
    self.firstLabel.text = data.first;
    self.secondLabel.text = data.second;
    [self invalidateIntrinsicContentSize];
}

@end

主视图 - 有一个表视图作为子视图

这是显示的实际视图。作为更大应用程序的一部分,该视图随后显示在垂直 UIStackView 中。

这个视图有一个表视图作为唯一的子视图,并且表视图通过 AutoLayout 固定在这个视图的边缘。 UITableView 实际上是另一个名为“AutosizingTableView”的类的实例,用于使表格视图自动调整大小(没有这个,表格的框架保持为零,并且表格视图数据源方法tableView:cellForRowAtIndexPath:,自从表格高度为零。此表格视图的代码包含在本节之后。

@interface MyView ()

@property (strong, nonatomic) AutosizingTableView *tableView;

@end

@implementation MyView

- (instancetype)init {
    return [self initWithFrame:CGRectZero];
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    if (self = [super initWithCoder:coder]) {
        [self initialize];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self initialize];
    }
    return self;
}

- (void)initialize {
    [self addSubview:self.tableView];
    
    [NSLayoutConstraint activateConstraints:@[
        [self.tableView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
        [self.tableView.topAnchor constraintEqualToAnchor:self.topAnchor],
        [self.tableView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
        [self.tableView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
        [self.tableView.widthAnchor constraintEqualToAnchor:self.widthAnchor]
    ]];
}

- (UITableView *)tableView {
    if (!self->_tableView) {
        self->_tableView = [[AutosizingTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
        self->_tableView.translatesAutoresizingMaskIntoConstraints = NO;
        self->_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        self->_tableView.rowHeight = UITableViewAutomaticDimension;
        self->_tableView.estimatedRowHeight = UITableViewAutomaticDimension;
        self->_tableView.allowsSelection = NO;
        self->_tableView.scrollEnabled = NO;
        self->_tableView.delegate = self;
        self->_tableView.dataSource = self;
        [self->_tableView registerClass:[MyTableViewCell class] forCellReuseIdentifier:@"myTableViewCell"];
    }
    return self->_tableView;
}

- (void)setdata:(NSArray<MyData *> *)data {
    self->_data = data;
    [self.tableView reloadData];
}

#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.data.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myTableViewCell" forIndexPath:indexPath];
    MyData *data = self.data[indexPath.row];
    cell.detail = detail;
    return cell;
}

@end

AutosizingTableView

如上一节所述,这只是为了使表格视图自动调整大小。如果没有这个,表格视图高度为零并保持为零,因为由于表格视图高度,tableView:cellForRowAtIndexPath: 方法永远不会被调用。

@implementation AutosizingTableView

- (CGSize)intrinsicContentSize {
    return self.contentSize;
}

- (void)setContentSize:(CGSize)contentSize {
    [super setContentSize:contentSize];
    [self invalidateIntrinsicContentSize];
}

@end

【问题讨论】:

    标签: ios objective-c uitableview autolayout nslayoutconstraint


    【解决方案1】:

    试试这个:

    - (void)initialize {
    [self.contentView setBackgroundColor:[UIColor systemTealColor]];
    [self.backgroundView setBackgroundColor:[UIColor systemGrayColor]];
    
    [self.contentView addSubview:self.firstLabel];
    [self.contentView addSubview:self.secondLabel];
    
    NSLayoutConstraint *heightConstraint = [self.heightAnchor constraintEqualToConstant:1.0f];
    [heightConstraint setPriority:50];
    
    [NSLayoutConstraint activateConstraints:@[
        [self.firstLabel.leadingAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.leadingAnchor],
        [self.firstLabel.topAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.topAnchor],
        [self.firstLabel.trailingAnchor constraintEqualToAnchor:self.centerXAnchor constant:-4.0f],
        
        [self.secondLabel.leadingAnchor constraintEqualToAnchor:self.centerXAnchor constant:4.0f],
        [self.secondLabel.topAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.topAnchor],
        [self.secondLabel.trailingAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.trailingAnchor],
        
        [self.contentView.layoutMarginsGuide.bottomAnchor constraintGreaterThanOrEqualToAnchor:self.firstLabel.bottomAnchor constant:20.0f],
        [self.contentView.layoutMarginsGuide.bottomAnchor constraintGreaterThanOrEqualToAnchor:self.secondLabel.bottomAnchor constant:20.0f],
        
        heightConstraint
    ]];
    }
    

    您应该将标签添加到 contentView 而不是直接添加单元格。

    【讨论】:

    • 解决了这个问题。太感谢了。我确实有另一个问题,标签由于某种原因被截断。我打算发布另一个关于此的问题,但我只能每隔一个半小时做一次。但是如果我在右边的标签上有一个非常大的字体,然后我在左边的标签中有很多文本,左边的标签将继续显示文本并包裹直到它得到相同的高度作为右边的标签。那时,它会截断。你知道可能出了什么问题吗?我会在有能力的时候发布一个新问题。谢谢。
    • 尝试删除您设置的垂直拥抱和抗压优先级。保持水平
    • @ashipma 请查看stackoverflow.com/questions/67326104/…,因为我已经非常清楚地说明了如何执行此操作。这个问题可以说是那个问题的重复。
    • @matt,是的,我已经添加了不等式约束,正如您在另一个问题上所建议的那样,这回答了我关于如何使约束适用于更大标签的问题。但是我遇到的另一个问题是我将标签直接添加到单元格而不是单元格的 contentView 属性中,因此通过这个问题得到了纠正。我还有一个问题,这就是为什么较长的标签会被截断为与另一个标签相同的高度。所以实际上,标签的高度与较短标签的 intrinsicContentSize 相同。
    • 是的,我不知道为什么会这样。看起来有其他东西限制了我们可以长到的高度。但正如你所看到的,我在自己的测试中没有遇到过这种情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多