两列自动调整UITableViewCell的大小 [英] Autosize UITableViewCell with two columns

查看:78
本文介绍了两列自动调整UITableViewCell的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个UITableViewCell,其中有两列.每列都是一个UILabel,每个标签都是多行(numberOfLines = 0).

我想要的是使表格视图单元格垂直设置,其大小取决于哪个标签更高.我为每个标签的左,右和顶部设置了约束,但是我不确定如何添加底部约束,因为它必须是对最高标签的约束.

这是我现在拥有的:

但这是我要实现的目标.但是左列或右列可能更高.在图片中,右列较高,但根据提供给它的数据,左列也可能较高.

我曾考虑过添加一个高度约束以将两个标签约束到相同的高度,然后从那里添加底部约束,但是较短的标签将不会垂直对齐,或者我不知道对齐它们的方法垂直而无需子类化UILabel或使用UITextView,如果可能的话,我宁愿不这样做.

是否有一种很好的方法可以使表格视图单元能够根据较高的列垂直地自动调整大小?感谢您的帮助.


更新

我根据提供的答案添加了两个其他约束.但是由于某种原因,我仍然无法获得它来自动调整表格单元格的大小.我在Interface Builder中将行高设置为自动.这是我当前配置的约束.

约束中是否有任何东西可以阻止表格视图单元的高度增加以匹配标签的高度?

我不确定这是否是问题,但是我尝试按照建议的方式向内容视图添加低优先级的高度约束,但是我无法添加约束,或者我不知道如何去做.我可以将高度限制添加到其他视图,但不能添加到表视图单元格的内容视图.

更新2

这是代码中的约束.它位于UITableViewCell子类中,并且此代码作为单元格初始化的一部分运行.

  [self addSubview:self.firstLabel];[self addSubview:self.secondLabel];NSLayoutConstraint * heightConstraint = [self.heightAnchor constraintEqualToConstant:1.0f];[heightConstraint setPriority:50];[NSLayoutConstraint activateConstraints:@ [[self.firstLabel.LeadingAnchor约束EqualToAnchor:self.contentView.layoutMarginsGuide.leadingAnchor],[self.firstLabel.topAnchor约束EqualToAnchor:self.contentView.layoutMarginsGuide.topAnchor常数:0.0f],[self.firstLabel.trailingAnchor约束EqualToAnchor:self.centerXAnchor常数:-4.0f],[self.secondLabel.leadingAnchor约束EqualToAnchor:self.centerXAnchor常数:4.0f],[self.secondLabel.firstBaselineAnchor约束EqualToAnchor:self.firstLabel.firstBaselineAnchor],[self.secondLabel.trailingAnchor约束EqualToAnchor:self.contentView.layoutMarginsGuide.trailingAnchor],[self.contentView.heightAnchor约束GreaterThanOrEqualToAnchor:self.firstLabel.heightAnchor常数:8.0f],[self.contentView.heightAnchor约束GreaterThanOrEqualToAnchor:self.secondLabel.heightAnchor常数:8.0f],heightConstraint]]; 

这是在设备上运行时的外观.这些标签都很短,除了第一个标签应该跨几行.但是由于某些原因,即使我将行数设置为0,并且我认为内容拥抱和内容抗压缩优先级设置为我认为应该正确的值,它也会被截断.

以下是我的标签的定义方式:

 -(UILabel *)firstLabel {如果(!self-> _firstLabel){self-> _firstLabel = [[UILabel alloc] init];self-> _firstLabel.translatesAutoresizingMaskIntoConstraints = NO;self-> _firstLabel.numberOfLines = 0;self-> _firstLabel.userInteractionEnabled =否;self-> _firstLabel.contentMode = UIViewContentModeScaleToFill;[self-> _firstLabel setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisHorizo​​ntal];[self-> _firstLabel setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisVertical];[self-> _firstLabel setContentCompressionResistancePriority:UILayoutPriorityAxis所需:UILayoutConstraintAxisHorizo​​ntal];[self-&_; _ firstLabel setContentCompressionResistancePriority:UILayoutPriorityAxis必需:UILayoutConstraintAxisVertical];self-> _firstLabel.textAlignment = NSTextAlignmentNatural;self-> _firstLabel.lineBreakMode = NSLineBreakByTruncatingTail;self-> _firstLabel.baselineAdjustment = UIBaselineAdjustmentAlignBaselines;self-> _firstLabel.adjustsFontSizeToFitWidth = NO;//TODO:删除此self-> _firstLabel.backgroundColor = [UIColor orangeColor];}返回self-> _firstLabel;}-(UILabel *)secondLabel {如果(!self-> _secondLabel){self-> _secondLabel = [[UILabel alloc] init];self-> _secondLabel.translatesAutoresizingMaskIntoConstraints = NO;self-> _secondLabel.numberOfLines = 0;self-> _secondLabel.userInteractionEnabled =否;self-> _secondLabel.contentMode = UIViewContentModeScaleToFill;[self-> _secondLabel setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisHorizo​​ntal];[self-> _secondLabel setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisVertical];[self-> _secondLabel setContentCompressionResistancePriority:UILayoutPriorityAxis必需:UILayoutConstraintAxisHorizo​​ntal];[self-> _secondLabel setContentCompressionResistancePriority:UILayoutPriorityAxis必需:UILayoutConstraintAxisVertical];self-> _secondLabel.textAlignment = NSTextAlignmentNatural;self-> _secondLabel.lineBreakMode = NSLineBreakByTruncatingTail;self-> _secondLabel.baselineAdjustment = UIBaselineAdjustmentAlignBaselines;self-> _secondLabel.adjustsFontSizeToFitWidth = NO;//TODO:删除此self-> _secondLabel.backgroundColor = [UIColor yellowColor];}返回self-> _secondLabel;} 

解决方案

是的,当您了解约束不等式和优先级时,这非常简单.在这里,左侧的标签更长:

在这里,右边的标签更长:

黄色视图(代表此处的表格视图单元格)的大小与标签中的较大标签相同.

那是怎么做的?除了按常规方式将标签固定在顶部,左侧和右侧之外,超级视图(黄色视图)底部还具有两个大于或等于的约束,一个约束于每个标签的底部;一个约束位于每个标签的底部.并且它本身会以非常低的优先级被赋予一个很小的高度(这是一种告诉布局引擎在遵循这些不等式的同时使高度尽可能小的方法,否则这将是模棱两可的).


编辑似乎有人怀疑这是否适用于实际的表格视图,因此这里证明它确实可行.

I have a UITableViewCell that has two columns in it. Each column is a UILabel and each label is multiline (numberOfLines = 0).

What I would like is to have the table view cell vertically sized based on whichever label is taller. I have constraints setup for the left right and top of each label, but I am not sure how to add the bottom constraints since it needs to be a constraint on the tallest label.

Here is what I have right now:

But this is what I am trying to achieve. But either the left or the right column could be taller. In the picture, the right column is taller, but it just as well could be the left column depending on the data supplied to it.

I have thought about adding a height constraint to constraint both labels to the same height and then adding the bottom constraint from there, but then the shorter label will not be vertically aligned, or I do not know of a way of aligning them vertically without subclassing UILabel or using UITextView, which I would prefer to not do if possible.

Is there a good way to have the table view cell be able to vertically auto-size based on whichever column is taller? Thanks for your help.


Update

I have added two additional constraints based on the answer provided. But for some reason I still cannot get it to autosize the table cell. I have the row height set to automatic in Interface Builder. Here are the constraints I have configured currently.

Is there anything in the constraints that would prevent the table view cell from increasing in height to match the height of the labels?

I am not sure if this is the problem or not, but I tried to add a low priority height constraint to the content view also, as was suggested, but I am unable to add the constraint or I do not know how to do that. I can add a height constraint to other views, but not to the content view of the table view cell.

Update 2

Here are the constraints in code. This is in a UITableViewCell subclass and this code runs as part of the initialization of the cell.

[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 constant:0.0f],
    [self.firstLabel.trailingAnchor constraintEqualToAnchor:self.centerXAnchor constant:-4.0f],
    
    [self.secondLabel.leadingAnchor constraintEqualToAnchor:self.centerXAnchor constant:4.0f],
    [self.secondLabel.firstBaselineAnchor constraintEqualToAnchor:self.firstLabel.firstBaselineAnchor],
    [self.secondLabel.trailingAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.trailingAnchor],
    
    [self.contentView.heightAnchor constraintGreaterThanOrEqualToAnchor:self.firstLabel.heightAnchor constant:8.0f],
    [self.contentView.heightAnchor constraintGreaterThanOrEqualToAnchor:self.secondLabel.heightAnchor constant:8.0f],
    
    heightConstraint
]];

Here is what it looks like when run on the device. The labels are all short, except the first one, which is supposed to span several lines. But for some reason, it is being truncated even though I have the number of lines set to 0 and I think the content hugging and content compression resistance priorities set to what I think should be correct.

Here are how my labels are defined:

- (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;
        
        //TODO: remove this
        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;
        
        //TODO: remove this
        self->_secondLabel.backgroundColor = [UIColor yellowColor];
    }
    return self->_secondLabel;
}

解决方案

Yes, it's pretty straightforward when you understand about constraint inequalities and priorities. Here, the label on the left is longer:

Here, the label on the right is longer:

The yellow view, which stands in for a table view cell here, is sized to the larger of the labels.

How is that done? In addition to the labels being pinned top, left, and right in the normal way, the superview (yellow view) bottom has two greater-than-or-equal constraints, one to the bottom of each label; and it is itself given a very small height at a very low priority (as a way of telling the layout engine to make the height as small as possible while still obeying the inequalities, which would otherwise be ambiguous).


EDIT There appears to be some doubt that this would work for an actual table view, so here's proof that it does.

这篇关于两列自动调整UITableViewCell的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆