我正在创建一个应用程序,它将在UILabel中有一个问题,并在UITableView中显示多项选择的答案,每行显示多项选择。问题和答案会有所不同,所以我需要这个UITableView的高度是动态的。
我想为桌子周围找一个合适的尺寸。其中,表的框架被设置为所有内容的高度。
有人能给我一些建议吗?
我正在创建一个应用程序,它将在UILabel中有一个问题,并在UITableView中显示多项选择的答案,每行显示多项选择。问题和答案会有所不同,所以我需要这个UITableView的高度是动态的。
我想为桌子周围找一个合适的尺寸。其中,表的框架被设置为所有内容的高度。
有人能给我一些建议吗?
当前回答
在表视图上为contentSize属性添加一个观察者,并相应地调整帧大小
[your_tableview addObserver:self forKeyPath:@"contentSize" options:0 context:NULL];
然后在回调中:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
CGRect frame = your_tableview.frame;
frame.size = your_tableview.contentSize;
your_tableview.frame = frame;
}
希望这对你有所帮助。
其他回答
我的Swift 5实现是将tableView的高度约束设置为其内容的大小(contentSize.height)。此方法假定您正在使用自动布局。这段代码应该放在cellForRowAt tableView方法中。
tableView.heightAnchor.constraint(equalToConstant: tableView.contentSize.height).isActive = true
这适用于我使用自动布局,与表视图只有一个部分。
func getTableViewContentHeight(tableView: UITableView) -> CGFloat {
tableView.bounds = CGRect(x: 0, y: 0, width: 300, height: 40)
let rows = tableView.numberOfRows(inSection: 0)
var height = CGFloat(0)
for n in 0...rows - 1 {
height = height + tableView.rectForRow(at: IndexPath(row: n, section: 0)).height
}
return height
}
我在设置自动布局时调用这个函数(这里的示例使用SnapKit,但你知道的):
let height = getTableViewContentHeight(tableView: myTableView)
myTableView.snp.makeConstraints {
...
...
$0.height.equalTo(height)
}
我希望UITableView只和单元格的总和一样高;我循环遍历单元格,并积累单元格的总高度。因为表格视图的大小是CGRect。此时,我需要设置边界,以便能够尊重单元格定义的自动布局规则。我将大小设置为一个足够大的任意值。实际的大小将在稍后由自动布局系统计算。
如果你使用AutoLayout,有一个更好的方法:改变决定高度的约束。只需计算表内容的高度,然后找到约束并更改它。下面是一个例子(假设决定表高度的约束实际上是一个关系为“Equal”的高度约束):
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
for constraint in tableView.constraints {
if constraint.firstItem as? UITableView == tableView {
if constraint.firstAttribute == .height {
constraint.constant = tableView.contentSize.height
}
}
}
}
如果您希望您的表是动态的,您将需要使用一个基于上面所详述的表内容的解决方案。如果你只是想显示一个更小的表,你可以使用容器视图并在其中嵌入一个UITableViewController——UITableView将根据容器大小调整大小。
这避免了大量的计算和对布局的调用。
Swift 5和4.2解决方案没有KVO, DispatchQueue,也没有自己设置约束。
这个解决方案基于古尔兹的回答。
1)创建UITableView的子类:
import UIKit
final class ContentSizedTableView: UITableView {
override var contentSize:CGSize {
didSet {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
layoutIfNeeded()
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
}
2)添加一个UITableView到你的布局和设置约束的所有方面。将它的类设置为contentsizetableview。
3)你应该会看到一些错误,因为Storyboard没有考虑子类的intrinsicContentSize。通过打开大小检查器并将intrinsicContentSize重写为一个占位符值来修复此问题。这是设计时的重写。在运行时,它将在contentsizetableview类中使用重写
更新:更改了Swift 4.2的代码。如果你使用的是以前的版本,使用UIViewNoIntrinsicMetric而不是UIView.noIntrinsicMetric