如何在表视图中的UITableViewCells中使用“自动布局”,让每个单元格的内容和子视图确定行高度(自身/自动),同时保持平滑的滚动性能?
当前回答
在我的例子中,填充是因为sectionHeader和sectionFooter的高度,故事板允许我将其更改为最小值1。因此,在viewDidLoad方法中:
tableView.sectionHeaderHeight = 0
tableView.sectionFooterHeight = 0
其他回答
我刚刚遇到一个非常重要的问题,作为回答发布。
@smileyborg的回答基本正确。但是,如果自定义单元格类的layoutSubviews方法中有任何代码,例如设置preferredMaxLayoutWidth,则不会使用以下代码运行:
[cell.contentView setNeedsLayout];
[cell.contentView layoutIfNeeded];
这让我困惑了一阵子。然后我意识到这是因为它们只触发contentView上的layoutSubview,而不是单元格本身。
我的工作代码如下:
TCAnswerDetailAppSummaryCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TCAnswerDetailAppSummaryCell"];
[cell configureWithThirdPartyObject:self.app];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height;
注意,如果您正在创建一个新的单元格,我很确定您不需要调用setNeedsLayout,因为它应该已经设置好了。在保存对单元格的引用的情况下,您可能应该调用它。不管怎样,它都不会造成任何影响。
另一个提示是,如果您使用的是单元格子类,则需要设置preferredMaxLayoutWidth等属性。正如@smileyborg提到的,“您的表视图单元格的宽度尚未固定到表视图的宽度”。这是正确的,如果您在子类中而不是在视图控制器中进行工作,则会遇到麻烦。但是,此时可以使用表格宽度简单地设置单元格框架:
例如,在计算高度时:
self.summaryCell = [self.tableView dequeueReusableCellWithIdentifier:@"TCAnswerDetailDefaultSummaryCell"];
CGRect oldFrame = self.summaryCell.frame;
self.summaryCell.frame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y, self.tableView.frame.size.width, oldFrame.size.height);
(我碰巧缓存了这个特定的单元以供重用,但这无关紧要)。
我只是对rowHeight和estimatedRowHeight的两个值进行了一些愚蠢的尝试和错误,并认为它可能会提供一些调试细节:
如果同时设置它们,或者仅设置估计的RowHeight,则将获得所需的行为:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 1.00001 // MUST be greater than 1
建议您尽最大努力得到正确的估计,但最终结果并无不同。这只会影响你的表现。
如果只设置rowHeight,即只执行以下操作:
tableView.rowHeight = UITableViewAutomaticDimension
您的最终结果不会如预期:
如果将estimatedRowHeight设置为1或更小,则无论rowHeight如何,都会崩溃。
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 1
我崩溃了,出现以下错误消息:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'table view row height
must not be negative - provided height for index path (<NSIndexPath:
0xc000000000000016> {length = 2, path = 0 - 0}) is -1.000000'
...some other lines...
libc++abi.dylib: terminating with uncaught exception of type
NSException
@smileyborg提出的解决方案几乎是完美的。如果您有一个自定义单元格,并且需要一个或多个具有动态高度的UILabel,则systemLayoutSizeFittingSize方法与启用自动布局相结合将返回一个CGSizeZero,除非您将所有单元格约束从单元格移到其contentView(如@TomSwift在这里建议的那样,如何调整超视图的大小以适应具有自动布局的所有子视图?)。
为此,您需要在自定义UITableViewCell实现中插入以下代码(感谢@Adrian)。
- (void)awakeFromNib{
[super awakeFromNib];
for (NSLayoutConstraint *cellConstraint in self.constraints) {
[self removeConstraint:cellConstraint];
id firstItem = cellConstraint.firstItem == self ? self.contentView : cellConstraint.firstItem;
id seccondItem = cellConstraint.secondItem == self ? self.contentView : cellConstraint.secondItem;
NSLayoutConstraint *contentViewConstraint =
[NSLayoutConstraint constraintWithItem:firstItem
attribute:cellConstraint.firstAttribute
relatedBy:cellConstraint.relation
toItem:seccondItem
attribute:cellConstraint.secondAttribute
multiplier:cellConstraint.multiplier
constant:cellConstraint.constant];
[self.contentView addConstraint:contentViewConstraint];
}
}
将@smileyborg答案与此混合应该会奏效。
对于上面的iOS 8,这非常简单:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 80
self.tableView.rowHeight = UITableView.automaticDimension
}
or
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableView.automaticDimension
}
但对于iOS 7,关键是计算自动布局后的高度:
func calculateHeightForConfiguredSizingCell(cell: GSTableViewCell) -> CGFloat {
cell.setNeedsLayout()
cell.layoutIfNeeded()
let height = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingExpandedSize).height + 1.0
return height
}
重要的
如果有多行标签,请不要忘记将numberOfLines设置为0。不要忘记label.preferredMaxLayoutWidth=CGRectGetWidth(tableView.bounds)
完整的示例代码在这里。
在我的例子中,我必须创建一个自定义单元格,其中包含来自服务器的图像,可以是任何宽度和高度。以及两个具有动态大小(宽度和高度)的UILabels
我在回答自动布局和编程实现了同样的效果:
基本上在@smileyBorg以上的回答有所帮助,但systemLayoutSizeFittingSize从未对我奏效,在我的方法中:
1.不使用自动行高计算属性。2.不使用估计高度3.不需要不必要的更新约束。4.不使用自动首选最大布局宽度。5.不使用systemLayoutSizeFittingSize(应该使用但不适用于我,我不知道它在内部做什么),而是使用我的方法-(float)getViewHeight,我知道它在在内部做些什么。
当我使用几种不同的方式显示单元格时,UITableView单元格中的高度是否可能不同?
推荐文章
- 自动调整掩码大小编程vs接口生成器/ xib / nib
- NSUserDefaults -如何判断一个键是否存在
- Xcode UI测试用例中的延迟/等待
- 裁剪一个UIImage
- 这个应用程序是否使用广告标识符(IDFA)?—AdMob 6.8.0
- iOS 7: UITableView显示在状态栏下
- 如何产生类似ios7模糊视图的效果?
- 在一个故事板,我如何使一个自定义单元用于多个控制器?
- 将故事板从iPhone转换为iPad
- 如何检查文档文件夹中是否存在文件?
- 是否有一种方法可以遍历字典?
- iPhone上UIView和UILabels的渐变
- keychain上的分发证书中缺少私钥
- 在实现API时,我如何避免在块中捕获自我?
- 如何创建一个Swift Date对象?