我想计算UITableView
的内容大小。我正在使用身高UITableViewAutomaticDimension
的自动布局。
在重新加载tableview后尝试获取[UITableView contentsize]
,在这种情况下,根据estimatedRowHeight
计算身高。
self.tableView.estimatedRowHeight = 50;
self.tableView.rowHeight = UITableViewAutomaticDimension;
代表 -
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
尝试获取内容大小并将其指定为高度约束。
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
self.tableHeightConstraint.constant = self.tableView.contentSize.height;
有什么建议吗?提前谢谢。
修改
最后我通过一些调整解决了我的问题。在重新加载表格数据之前,我将tableview高度更改为max(在我的情况下300是最大值),因此tableview可以调整所有单元格的大小。
self.tableHeightConstraint.constant = 300;
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
self.tableHeightConstraint.constant = self.tableView.contentSize.height;
感谢您的帮助。
答案 0 :(得分:36)
最后我通过一些调整解决了我的问题。在重新加载表格数据之前,我将tableview高度更改为max(在我的情况下300是最大值),因此tableview可以调整所有单元格的大小。
self.tableHeightConstraint.constant = 300;
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
self.tableHeightConstraint.constant = self.tableView.contentSize.height;
发布此内容对其他人有帮助。
答案 1 :(得分:13)
最后,我理解你的问题,这是解决方案。
我希望你已经做到了。
UITableView
的修复高度。IBOutlet
高度的约束UITableView
。viewDidLayoutSubviews
方法下,您可以在填充数据后获得原始UITableView
高度。更新以下代码:
override func viewDidLayoutSubviews() {
constTableViewHeight.constant = tableView.contentSize.height
}
更新
self.tableView.estimatedRowHeight = UITableViewAutomaticDimension;
请检查一下。
答案 2 :(得分:7)
在表格视图初始化期间将estimatedRowHeight设置为零,并将以下代码添加到viewDidLayoutSubviews中,为我工作!
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.constant = tableView.contentSize.height
答案 3 :(得分:2)
您可以尝试两件事,
在tableView完全重新加载后,在延迟几秒后调用以下方法。
- (void)adjustHeightOfTableview
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
//In my case i had to call this method after some delay, because (i think) it will allow tableView to reload completely and then calculate the height required for itself. (This might be a workaround, but it worked for me)
[self performSelector:@selector(adjustHeightOfTableview) withObject:nil afterDelay:0.3];
});
}
当您调用上述方法时,请不要返回estimatedHeightForRow,
/*
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 44;
}
*/
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
试一试,它可以帮助你解决问题。
答案 4 :(得分:2)
上述所有解决方案都不适用于我的案例。 我最终使用了这样的观察者:
self.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if let obj = object as? UITableView {
if obj == self.tableView && keyPath == "contentSize" {
if let newSize = change?[NSKeyValueChangeKey.newKey] as? CGSize {
self.tableView.frame.size.height = newSize.height
}
}
}
}
答案 5 :(得分:1)
对我来说,解决方案是将preg_match()
设置为比我认为可以显示的数据更大的值。
由于某种原因,这确保了estimatedRowHeight
属性未用于确定estimatedRowHeight
。我没有显示滚动指示器,因此contentSize
离开时对我来说并不重要。
答案 6 :(得分:0)
您也可以将UITableView
子类化,然后从您肯定拥有合适的layoutSubviews()
的{{1}}处呼叫任何您想要的人(即,它是容器视图)。
答案 7 :(得分:0)
快速使用
tableView.invalidateIntrinsicContentSize()
tableView.layoutIfNeeded()
在reloadData()之后 和
tableView.contentSize.height
将完美工作。 Example on medium
答案 8 :(得分:0)
在我的情况下,我不使用tableView的高度约束-使用自动布局,设置了顶部和底部约束,并且只有底部约束进入/退出编辑模式时才会发生变化。
Tzegenos's answer的修改方式如下:
1.在viewDidLoad()中添加tableView.estimatedRowHeight = 0
2.添加以下内容:
override func viewDidLayoutSubviews() {
// 60 is row's height as set by tableView( cellRowAt )
// places is of type [String] to be used by tableView
tableView.contentSize.height = 60 * CGFloat(places.count)
}
答案 9 :(得分:0)
使用 KVO 是解决此 contentSize
问题的最佳实践,您不需要使用 layoutIfNeeded
强制 TableView
更新其布局。如果 max_height (CGFloat.greatestFiniteMagnitude
) 太大或者手动设置高度不是一个好主意,则使用 @OnkarK 答案(已接受的答案)会导致滞后。
使用 Swift KVO:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
}
override func viewWillDisappear(_ animated: Bool) {
self.tableView.removeObserver(self, forKeyPath: "contentSize")
super.viewWillDisappear(true)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?){
if keyPath == "contentSize" {
if let value = change?[.newKey]{
let size = value as! CGSize
self.tableHeightConstraint.constant = size.height
}
}
}
使用组合:
override func viewDidLoad() {
super.viewDidLoad()
tableView.publisher(for: \.contentSize)
.receive(on: RunLoop.main)
.sink { size in
self.tableHeightConstraint.constant = size.height
}.store(in: &cancellables)
}
使用 RxSwift:
override func viewDidLoad() {
super.viewDidLoad()
tableView.rx.observe(CGSize.self, "contentSize")
.filter({$0 != nil})
.subscribe(onNext: { size in
self.tableHeightConstraint.constant = size!.height
}).disposed(by: bag)
}
答案 10 :(得分:0)
基于块的 KVO 方法
var contentSizeObserver: NSKeyValueObservation?
@IBOutlet weak var myTableView: UITableView!
@IBOutlet weak var tableHeightConstraint: NSLayoutConstraint!
override func viewDidLoad() {
contentSizeObserver = myTableView.observe(\UITableView.contentSize, options: [NSKeyValueObservingOptions.new], changeHandler: { _, change in
if let contentSize = change.newValue {
self.tableHeightConstraint.constant = contentSize.height
}
})
}
override func viewWillDisappear(_ animated: Bool) {
contentSizeObserver = nil
super.viewWillDisappear(true)
}