UITableView 最大尺寸,同时尊重自动布局约束

Posted

技术标签:

【中文标题】UITableView 最大尺寸,同时尊重自动布局约束【英文标题】:UITableView max size while respecting autolayout constraints 【发布时间】:2018-09-17 11:20:57 【问题描述】:

所以我想要做的是有一个表格视图,它在尊重自动布局约束的同时最大化它的大小。现在我有一个表格视图,它最大化了它的大小,但它不能滚动。

public class ExpandingTableView2: UITableView 

    override public func reloadData() 
        super.reloadData()
        self.setNeedsLayout()
        self.invalidateIntrinsicContentSize()
    

    override public func layoutSubviews() 
        super.layoutSubviews()
        if !self.bounds.size.equalTo(self.intrinsicContentSize) 
            self.invalidateIntrinsicContentSize()

        
    

    override public var intrinsicContentSize: CGSize 
        self.layoutIfNeeded()
        let intrinsicContentSize = super.contentSize
        return intrinsicContentSize
    

【问题讨论】:

不要最大化tableview大小,因为tableview大小将等于内容大小,这将使其不可滚动,而是让你tableview宽度和高度等于超级视图。 tableview 也可以很小,有时只有一行。然后我不希望它被最大化 增加 tableview 大小是一个非常糟糕的主意。理想情况下,tableview 将具有适合屏幕内部的大小。编译器不知道什么对你可见,什么不可见。因此,当您增加 tableview 的大小时,它会超出可见区域,从而隐藏底部的内容并且无法访问,因为 contentsize 在 tableview 大小范围内,只是对您不可见。 【参考方案1】:

您可以通过创建高度约束的出口来根据内容大小计算tableview高度:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    if tableViewHeightConstraint.constant != tableView.contentSize.height && tableViewHeightConstraint.constant < view.frame.height // This will prevent to increase tableview height beyond the view and let it scroll

        setupHeightConstraintForTableView(tableView.contentSize.height)
    

   // rest of the code


func setupHeightConstraintForTableView(_ heightValue: CGFloat) 
    tableViewHeightConstraint.constant = heightValue
    self.updateConstraintsIfNeeded()

【讨论】:

您的逻辑是正确的,但是在您的实现中,如果视图中除了 tableview 之外还有其他内容,这将不起作用。您可能想检查视图是否以其他方式向外显示。 @RakeshaShastri 我完全同意,如果除了 tableview 之外还包含任何其他子视图,它需要进行一些重构。但根据问题,它只有表格视图。如果有任何子视图,我们需要根据它们的位置相应地放置条件。 tableview 位于另一个视图中,该视图具有基于屏幕高度和一些标签高度的高度约束。 @TommySadiqHinrichsen 根据该超级视图给出 if 条件。 另外,如果你指的是视图的高度,它应该是view.frame.height?并且不确定updateConstraintsIfNeeded() 是否会触发布局更新。我只见过layoutIfNeeded() 使用过。【参考方案2】:

这里重要的是保持控制 tableview 最大高度的约束高于用于设置其高度的约束。我还将 tableview 的内容压缩阻力设置为 250。

public class ExpandingTableView: UITableView 

    @IBOutlet public weak var heightConstraint: NSLayoutConstraint?

    override public func reloadData() 

        guard let heightConstraint = self.heightConstraint, heightConstraint.priority.rawValue < 750  else  return 

        var height: CGFloat = 0.0
        for section in 0..<(self.dataSource?.numberOfSections?(in: self) ?? 1) 
            for row in 0..<(self.dataSource?.tableView(self, numberOfRowsInSection: section) ?? 0) 
                let rowHeight = (self.delegate?.tableView?(self, heightForRowAt: IndexPath(row: row, section: section))) ?? self.rowHeight
                height += rowHeight
            
        

        heightConstraint.constant = height

        super.reloadData()
        self.setNeedsLayout()
    


【讨论】:

以上是关于UITableView 最大尺寸,同时尊重自动布局约束的主要内容,如果未能解决你的问题,请参考以下文章

具有自动布局和最大尺寸保持纵横比的 UIImageView

自动布局和 UIImageViews

在自动布局和尺寸类中屏蔽图像

UITableView 部分标题的自动布局问题

在 UITableView 中使用自动布局进行动态单元格布局和可变行高

在 UITableView 中使用自动布局进行动态单元格布局和可变行高