[英]Dynamically size Table View Cells using Auto Layout constraints
I have revised the question completely after my latest findings. 在我的最新发现之后,我完全修改了这个问题。
My goal is to implement the following effect: 我的目标是实现以下效果:
Please note that I am aware, that this can be achieved by inserting/deleting cells below the selected one, I already have a successful implementation using that method . 请注意,我知道,这可以通过插入/删除所选单元格下方的单元格来实现, 我已经使用该方法成功实现了 。
This time, I want to try to achieve this using Auto Layout constraints. 这次,我想尝试使用Auto Layout约束来实现这一点。
I have a sample project available for anyone to check , and also opened an issue . 我有一个示例项目可供任何人查看 ,也打开了一个问题 。 To summarize, here's what I've tried so far:
总结一下,这是我到目前为止所尝试的内容:
I have the following views as actors here: 我在这里作为演员有以下观点:
I have set up Auto Layout constraints within my cell the following way (please note that this is strictly pseudo-language): 我已经按照以下方式在我的单元格中设置了自动布局约束(请注意,这是严格的伪语言):
I have a custom UITableViewCell
subclass, with multiple outlets, but the most important here is an outlet for the height constraint mentioned previously: the idea here is to set its constant
to 0 by default, but when the cell is selected, set it to 44, so it becomes visible: 我有一个自定义的
UITableViewCell
子类,有多个出口,但最重要的是前面提到的高度约束的出口:这里的想法是默认将其constant
设置为0,但是当选择单元格时,将其设置为44 ,它变得可见:
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
detailViewHeightConstraint.constant = selected ? detailViewDefaultHeight : 0
UIView.animateWithDuration(0.3) {
self.layoutIfNeeded()
}
}
I have the following result: 我有以下结果:
So the effect is working, but not exactly how I originally imagined. 所以效果是有效的,但不完全是我最初的想象。 Instead of pushing the main view up, I want the cell's height to grow when the detail view is shown, and shrink back when it's hidden.
我没有推动主视图,而是希望细胞的高度在显示细节视图时增长 ,并在隐藏时收缩 。
I have examined my layout hierarchy during runtime: 我在运行时检查了我的布局层次结构:
What I need is the following: the height of table view cell's content view should be equal to 我需要的是:表格视图单元格内容视图的高度应该等于
How do I have to set my constraints to achieve that? 我如何设置约束来实现这一目标?
After a significant amount of research, I think I've found the solution with the help of this great article. 经过大量的研究,我想我已经在这篇伟大的文章的帮助下找到了解决方案。
Here are the steps needed to make the cell resize: 以下是使单元格调整大小所需的步骤:
Within the Main, and Detail Views, I have originally set the labels to be horizontally and vertically centered. 在Main和Detail Views中,我最初将标签设置为水平和垂直居中。 This isn't enough for self sizing cells.
这对于自我调整细胞是不够的。 The first thing I needed is to set up my layout using vertical spacing constraints instead of simple alignment:
我需要的第一件事是使用垂直间距约束而不是简单对齐来设置我的布局:
Additionally you should set the Main Container's vertical compression resistance to 1000. 此外,您应将主容器的垂直压缩阻力设置为1000。
The detail view is a bit more tricky: Apart from creating the appropriate vertical constraints, you also have to play with their priorities to reach the desired effect: 细节视图有点棘手:除了创建适当的垂直约束外,您还必须使用它们的优先级来达到所需的效果:
The main idea is the following: 主要想法如下:
I had to modify my UITableViewCell
subclass to support these operations: 我不得不修改我的
UITableViewCell
子类来支持这些操作:
// `showDetails` is exposed to control, whether the cell should be expanded
var showsDetails = false {
didSet {
detailViewHeightConstraint.priority = showsDetails ? lowLayoutPriority : highLayoutPriority
}
}
override func awakeFromNib() {
super.awakeFromNib()
detailViewHeightConstraint.constant = 0
}
To trigger the behavior, we must override tableView(_:didSelectRowAtIndexPath:)
: 要触发行为,我们必须覆盖
tableView(_:didSelectRowAtIndexPath:)
:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
switch expandedIndexPath {
case .Some(_) where expandedIndexPath == indexPath:
expandedIndexPath = nil
case .Some(let expandedIndex) where expandedIndex != indexPath:
expandedIndexPath = nil
self.tableView(tableView, didSelectRowAtIndexPath: indexPath)
default:
expandedIndexPath = indexPath
}
}
Notice that I've introduced expandedIndexPath
to keep track of our currently expanded index: 请注意,我已经引入了
expandedIndexPath
来跟踪我们当前扩展的索引:
var expandedIndexPath: NSIndexPath? {
didSet {
switch expandedIndexPath {
case .Some(let index):
tableView.reloadRowsAtIndexPaths([index], withRowAnimation: UITableViewRowAnimation.Automatic)
case .None:
tableView.reloadRowsAtIndexPaths([oldValue!], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
}
Setting the property will result in the table view reloading the appropriate indexes, giving us a perfect opportunity to tell the cell, if it should expand: 设置属性将导致表视图重新加载适当的索引,为我们提供了一个告诉单元格的完美机会,是否应该展开:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ExpandableTableViewCell
cell.mainTitle = viewModel.mainTitleForRow(indexPath.row)
cell.detailTitle = viewModel.detailTitleForRow(indexPath.row)
switch expandedIndexPath {
case .Some(let expandedIndexPath) where expandedIndexPath == indexPath:
cell.showsDetails = true
default:
cell.showsDetails = false
}
return cell
}
The last step is to enable self-sizing in viewDidLoad()
: 最后一步是在
viewDidLoad()
启用自我调整大小:
override func viewDidLoad() {
super.viewDidLoad()
tableView.contentInset.top = statusbarHeight
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 125
}
Here is the result: 结果如下:
Cells now correctly size themselves. 细胞现在可以自己调整大小 You may notice that the animation is still a bit weird, but fixing that does not fall into the scope of this question.
你可能会注意到动画仍然有点奇怪,但修复它不属于这个问题的范围。
Conclusion: this was way harder than it should be. 结论:这比应该的更难。 😀 I really hope to see some improvements in the future.
😀我真的希望看到未来会有一些改进。
This is in obj-c, but I'm sure you'll handle that: 这是obj-c,但我相信你会处理它:
Add in your viewDidLoad:
在
viewDidLoad:
添加viewDidLoad:
self.tableView.estimatedRowHeight = self.tableView.rowHeight; self.tableView.rowHeight = UITableViewAutomaticDimension;
This will enable self sizing cells for your tableView, and should work on iOS8+ 这将为tableView启用自定义单元格,并且应该可以在iOS8 +上运行
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.