如何在单元格动态调整大小时获取UITableView的高度?

时间:2016-10-17 06:41:07

标签: ios swift uitableview

我有一个UITableView,其中包含动态调整大小的单元格。这意味着我已经设置:

tableView.estimatedRowHeight = 50.0
tableView.rowHeight = UITableViewAutomaticDimension

现在我想获得整个表格视图的高度。我尝试通过tableView.contentSize.height但只返回估计的行高,而不是表视图的实际动态高度。

如何获得整个表格视图的动态高度?

9 个答案:

答案 0 :(得分:19)

我最终破解了一个解决方案:

tableView.contentSize.height不适用于动态单元格,因为它们只返回单元格数* estimatedRowHeight

因此,要获得动态表格视图高度,您需要查找所有可见单元格,并总结其高度。请注意,这仅适用于比屏幕短的表格视图。

然而,在我们执行上述操作以查找可见单元格之前,重要的是要知道注意我们需要在屏幕上获取表格视图,以便我们可以获得可见单元格。为此,我们可以将表格视图的高度约束设置为某个任意大的数字,以便它显示在屏幕上:

  1. 设置表格视图约束的高度:

    // Class variable heightOfTableViewConstraint set to 1000
    heightOfTableViewConstraint = NSLayoutConstraint(item: self.tableView, attribute: .height, relatedBy: .equal, toItem: containerView, attribute: .height, multiplier: 0.0, constant: 1000)
    containerView.addConstraint(heightOfTableViewConstraint)
    
  2. 调用tableView.layoutIfNeeded(),完成后,查找可见单元格,总结高度,然后编辑heightOfTableViewConstraint

    UIView.animate(withDuration: 0, animations: {
        self.tableView.layoutIfNeeded()
        }) { (complete) in
            var heightOfTableView: CGFloat = 0.0
            // Get visible cells and sum up their heights
            let cells = self.tableView.visibleCells
            for cell in cells {
                heightOfTableView += cell.frame.height
            }
            // Edit heightOfTableViewConstraint's constant to update height of table view
            self.heightOfTableViewConstraint.constant = heightOfTableView
    }
    

答案 1 :(得分:1)

上面提到的解决方案都很好。我尝试了一种不同的方法,它流畅且易于理解

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    tableView.removeObserver(self, forKeyPath: "contentSize")
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "contentSize"{
            if object is UITableView{
                if let newValue = change?[.newKey]{
                    let newSize = newValue as! CGSize
                    heightOfTableViewConstraint.constant = newSize.height
                }
            }
        }
    }

答案 2 :(得分:0)

您可以在扩展程序中添加它。

迅速4:

extension UITableView {

    // sums the height of visible cells
    func heightOfVisibleCells() -> CGFloat {
        return self.visibleCells.map({ $0.frame.height }).reduce(0, +)
    }

}

答案 3 :(得分:0)

尽管@leonardloo的回答部分正确,并且可能适合许多人的需求,但我还是想分享解决问题的方法。

我有一个带有大行的大tableView,并且有相同的问题。当我应用@leonardloo的答案时,我已经看到它仅绘制在开始时找到的可见单元格数量,并且绘制1行,而应该绘制5行(我的数据源计数)

要解决此问题,我发现了一个简单的解决方案:

UIView.animate(withDuration: 0, animations: {
self.tableView.layoutIfNeeded()
}) { (complete) in
    var heightOfTableView: CGFloat = 0.0
    // Get visible cells and sum up their heights
    let cells = self.tableView.visibleCells
    for cell in cells {
        heightOfTableView += cell.frame.height
    }
    // Edit heightOfTableViewConstraint's constant to update height of table view
    // Set tableView's constraint to height + 1 so that 
    // it can still draw the next visible cell it's supposed to.
    self.heightOfTableViewConstraint.constant = heightOfTableView + 1
}

这里的要点是让它绘制下一个单元格,以便通过将约束常量设置为height + 1来将它也计入visibleCells中。我已经测试过了,现在看起来像是一种魅力。

答案 4 :(得分:-1)

您应该在以下委托方法

中计算tableView的高度
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

    //Get the height required for the TableView to show all cells
    if indexPath.row() == (tableView.indexPathsForVisibleRows.last! as! NSIndexPath).row {
        //End of loading all Visible cells
        float heightRequiredForTable = tableView.contentSize.height

        //If cell's are more than 10 or so that it could not fit on the tableView's visible area then you have to go for other way to check for last cell loaded 
    }
}

答案 5 :(得分:-2)

我们可以使用UITableView扩展来获取高度,

   extension UITableView {    

       ///Get visible cell height
       var visibleCellsHeight: CGFloat {
            return visibleCells.reduce(0) { $0 + $1.frame.height }
       }
   }

答案 6 :(得分:-3)

只需维护CGFLoat类型的数组,并在UITableViewAutomaticDimension cellForRowAt

indexPath tableview代表中附加var cellHeight = [CGFloat]() func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { cellHeight.append(UITableViewAutomaticDimension) }
 DATEDIFF(DAY,ordr.DocDate,RDR1.U_ProgDate) datedifff

答案 7 :(得分:-3)

我会在这里添加我的答案,因为我有点挣扎。

我的表视图使用的是带有标题的部分,因此只是获取可见单元格的高度不起作用。我最终做的是首先为tableView设置一个超大的高度,以便全部添加内容。然后在cell的最后一个tableView上,我将tableView调整为与其content相同的高度。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  ... // do your normal cell processing

  // determine height and change it
  if indexPath.section == (self.sectionTitles.count - 1) && indexPath.row == (sectionData.count - 1) {

    UIView.animate(withDuration: 0, animations: {
      self.tableView.layoutIfNeeded()
    }) { complete in

      // Edit heightOfTableViewConstraint's constant to update height of table view
      self.tableViewHeightConstraint.constant = self.tableView.contentSize.height
    }
  }
}

答案 8 :(得分:-6)

你可以试试这段代码

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}