使用自动布局时的UITableView内容大小

Onk*_*arK 27 uitableview ios autolayout

我想计算我的内容大小UITableView.我正在使用高度自动布局UITableViewAutomaticDimension.

尝试[UITableView contentsize]重新加载tableview后,在这种情况下高度得到基于计算estimatedRowHeight.

self.tableView.estimatedRowHeight = 50;
self.tableView.rowHeight = UITableViewAutomaticDimension;
Run Code Online (Sandbox Code Playgroud)

代表 -

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return UITableViewAutomaticDimension;
}
Run Code Online (Sandbox Code Playgroud)

尝试获取内容大小并将其指定为高度约束.

[self.tableView reloadData];
[self.tableView layoutIfNeeded];
self.tableHeightConstraint.constant = self.tableView.contentSize.height;
Run Code Online (Sandbox Code Playgroud)

有什么建议?提前致谢.

编辑:

最后我通过一些调整解决了我的问题.在重新加载表格数据之前,我将tableview高度更改为max(在我的情况下300是max),因此tableview有空间来调整所有单元格的大小.

self.tableHeightConstraint.constant = 300;
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
self.tableHeightConstraint.constant = self.tableView.contentSize.height;
Run Code Online (Sandbox Code Playgroud)

感谢帮助.

Onk*_*arK 44

最后我通过一些调整解决了我的问题.在重新加载表格数据之前,我将tableview高度更改为max(在我的情况下300是max),因此tableview有空间来调整所有单元格的大小.

self.tableHeightConstraint.constant = CGFLOAT_MAX;
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
self.tableHeightConstraint.constant = self.tableView.contentSize.height;
Run Code Online (Sandbox Code Playgroud)

发布此信息对其他人有帮助.

  • 使用“CGFLOAT_MAX”会发出警告“此 NSLayoutConstraint 正在配置一个超出内部限制的常量”。将替换较小的值,但此问题应该得到解决。在 BOOL _NSLayoutConstraintNumberExceedsLimit() 上中断进行调试。这只会被记录一次。这将来可能会崩溃。`,也许使用较小的值会更好 (2认同)

Soh*_*mon 16

最后,我理解你的问题,这是解决方案.

我希望你已经这样做了.

  1. 首先考虑一些固定高度UITableView.
  2. 然后取约束IBOutletUITableView高度.
  3. 然后在viewDidLayoutSubviews方法下,您可以UITableView在填充数据后获得原始高度.

更新以下代码:

override func viewDidLayoutSubviews() {

   constTableViewHeight.constant = tableView.contentSize.height
}
Run Code Online (Sandbox Code Playgroud)

更新:

self.tableView.estimatedRowHeight = UITableViewAutomaticDimension;
Run Code Online (Sandbox Code Playgroud)

请检查一下.

  • 我做了同样的事.不工作.tableView.contentSize根据estimatedRowHeight计算得出.调整所有细胞大小后我需要高度. (4认同)

Tze*_*nos 9

通过在表视图初始化过程中将估计的行高度设置为零,并将以下代码添加到viewDidLayoutSubviews中,对我有用!

tableView.reloadData()
tableView.layoutIfNeeded()
tableView.constant = tableView.contentSize.height
Run Code Online (Sandbox Code Playgroud)

  • tableView.layoutIfNeeded() 为我修复了它,谢谢 (3认同)

Far*_*oko 9

使用UICollectionView自定义单元格大小对我来说是最好的解决方案,但如果您更喜欢UITableView,您可以使用 KVO 代替。

使用KVO是解决这个问题的最佳实践contentSize,你不需要使用layoutIfNeededKVO来强制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
        }
    }
} 
Run Code Online (Sandbox Code Playgroud)

使用组合:

override func viewDidLoad() {
   super.viewDidLoad()

   tableView.publisher(for: \.contentSize)
      .receive(on: RunLoop.main)
      .sink { size in
         self.tableHeightConstraint.constant = size.height
      }.store(in: &cancellables)
}
Run Code Online (Sandbox Code Playgroud)

使用 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)
}
Run Code Online (Sandbox Code Playgroud)


flo*_*bee 6

以上所有解决方案均不适用于我的情况。我最终使用了这样的观察者:

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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

快速使用

tableView.invalidateIntrinsicContentSize()
tableView.layoutIfNeeded()
Run Code Online (Sandbox Code Playgroud)

在reloadData()之后

tableView.contentSize.height
Run Code Online (Sandbox Code Playgroud)

会完美的。 媒介示例