使UITableView不可滚动并调整高度以容纳所有单元格

50

我正在将一个 UITableView 嵌入到另一个 UIScrollView 中。我只想让 UIScrollView 滚动,而不是 UITableView,因此我想禁用 UITableView 的滚动,并扩展 UITableViewcontentHeight 以一次性容纳所有动态内容。

我该如何实现这一点?


1
我想要在同一页中将子视图基本上集成到表视图中,而不是将整个视图作为表视图。 - Allen
1
所以你需要扩展你的TableView来适应那个表的长度。然后调整你的ScrollView的内容大小。 - Duyen-Hoa
1
如果其他子视图在表视图的顶部,您也可以将这些子视图添加到tableview中:按部分分离。第0节包含您的子视图1,第1节包含您的子视图2,第2节包含您所讨论的tableview的内容。 - Duyen-Hoa
我现在正处于这个点。一开始我把整个东西都放在一个表格里,但是处理多个部分并不好。现在我的问题是让表格视图根据内容数据扩展高度... - Nuno Gonçalves
@Allen 你得到答案了还是找到解决方案了?如果你已经找到了解决方案,请告诉我们。我也有同样的问题。 - G.Abhisek
显示剩余3条评论
9个回答

36
将tableView的滚动属性设为false。 第一种方法:
  1. 创建tableView的子类并覆盖intrinsicContentSize方法。
     class MyOwnTableView: UITableView {
    override var intrinsicContentSize: CGSize {
        self.layoutIfNeeded()
        return self.contentSize
    }

    override var contentSize: CGSize {
        didSet{
            self.invalidateIntrinsicContentSize()
        }
    }

    override func reloadData() {
        super.reloadData()
        self.invalidateIntrinsicContentSize()
    }
}
  • 在Interface Builder中,将tableView的类更改为MyOwnTableView(继承UITableView的子类)。

  • 为tableView设置自动行高。

  •     tableView.estimatedRowHeight = 60.0;
        tableView.rowHeight = UITableViewAutomaticDimension;
    

    第二种方法: 1. 为tableView创建一个具有任何值的高度约束,并连接一个IBOutlet,该IBOutlet会设置tableView的高度。

    1. 在重新加载数据后,将高度约束的常量设置为tableView.contentSize.height。

    self.tableViewHeight.constant = self.tableView.contentSize.height
    

    1
    非常好的答案,我看到了太多仅适用于视图控制器中的 tableView 的回答,还有根本没有任何解释的糟糕回答! - James Wolfe
    1
    @JamesWolfe 谢谢你! :) - Learner
    第一种方法不起作用。第二种方法很好用。 - Softlion
    1
    你的第二种方法非常适合使用Autolayout,谢谢! - Samuel Noyes
    这对我的使用情况起作用。我有一个位于滚动视图内的堆栈视图中的表视图。我需要表格扩展并显示其所有内容,而且我仍然需要表格,因为我想要滑动操作等功能。 - 72A12F4E

    12
    您需要将 UITableView 的滚动设置为 false
    tableview.scrollEnabled = false;
    
    tableview.frame = CGRectMake(tableview.frame.origin.x, tableview.frame.origin.y, tableview.frame.size.width, tableview.frame.size.height+(resultArray.count*HEIGHT_OF_CELL));
    

    然后,您可以通过将UITableView的内容大小设置为UITableView的高度,在UIScrollView上添加UITableView


    3
    单元格的动态高度怎么样? - E-Riddie
    1
    对于单元格的动态高度,您可以在 HeightForRowAtIndexPath 方法中计算总高度,然后相应地设置 scrollView 的框架。 - sourav
    好的,但是关于单元格的懒加载呢?如果你有20个单元格,它们一次性全部加载,而不是随着滚动进行懒加载。它们也没有被重复使用...有什么帮助吗? - Slavcho

    12

    设置tableView的尺寸与contentSize相等。

    override func viewDidLayoutSubviews() {
        tableView.frame.size = tableView.contentSize
    }
    

    2
    但这不会增加滚动视图的内容大小。内容大小保持不变。 - G.Abhisek
    内容缺失。 - Augusto

    10

    基本上,tableview的内容大小就是你所需要的。

    1. 将tableview的滚动设置为false,因为我们不希望有滚动行为。

    2. 获取tableview高度约束的引用。

    3. 设置tableViewHeightConstraint.constant = tableView.contentSize.height

    确保tableview的顶部、底部、前导和尾随约束已经就位。


    原因不明,tableView.contentSize.height 总是返回 0。 - Bijoy Thangaraj
    确保TableView的约束正确设置。 - Preetam Jadakar
    1
    基本上,tableview的内容大小就是你所需要的。这是关键点。谢谢。 - josher932

    3
    1. 将你的tableView框架尽可能覆盖所有行 -> tableView不需要滚动
    2. 将你的scrollView的contentSize设置为tableView的大小。

    还需要设置tableview.bounces = NO,以确保它不会夺取滚动焦点。 - Lytic

    2
    • First of all you need is to set up the UITableView Scrolling to NO
    • Second, create a height constraint for the table view and after you call [UITableView reloadData] change your height constraint

      tableViewHeightConstraint.constant = numberOfRows * heightOfEachRow;
      

    1

    你也可以使用Combine通过KVO来观察tableView的contentSize

    想法: 每当tableView的contentSize发生变化时,更新它的高度约束。

    我尝试使用此线程中的某些解决方案来实现它,但由于时间问题,有时会得到错误的contentSize值。使用KVO确保捕获所有contentSize的更新。

    1. 在tableView上定义一个高度约束
    2. 确保在tableView上禁用滚动
    3. 订阅KVO发布者以获取viewDidLoad中tableView的contentSize更改
    4. 将高度约束常量的值分配给您接收的值

    KVO部分的代码示例:

    class YourViewController: UIViewController {
        private var tokens: Set<AnyCancellable> = []
    
        func viewDidLoad() {
            super.viewDidLoad()
    
            tableView.publisher(for: \.contentSize).sink { [weak self] contentSize in
                self?.tableViewHeightConstraint.constant = contentSize.height
            }.store(in: &tokens)
        }
    }
    

    0

    如果使用固定内容的tableview作为scrollview的子视图,这非常容易实现,但您确切想要实现什么?动态单元格上下固定内容?在中心滑动部分永久显示内容?

    也许更清晰的设计是使用单个UITableView和表头、表尾或节头、节尾,利用UITableViewStyleGrouped与UITableViewStylePlain提供的自动行为。

    话虽如此,其他答案似乎也是一个不错的解决方案:

    Set scroll enabled false on table view
    Set tableview content size to sum of all cell sizes
    Set tableview frame to content size
    Adjust scroll view frame to account for dynamic table size if necessary
    Add table view to scroll view amidst other content
    

    另一种操作滚动行为的选项是在委托scrollView shouldStartScrolling或类似方法中检查tableview或scrollview,因为这将允许更多的UI控件灵活性


    0

    UITableView是一个滚动视图。虽然你不应该嵌套UIScrollviews,但你可以禁用表格视图的滚动。


    1
    我理解这个问题,但是我需要调整TableView的高度以适应所有的单元格。例如,如果我有5个单元格,禁用UITableView滚动将只隐藏最后2个单元格。 - Allen
    在UITableView数据源回调中分配UITableViewCell高度时,您可以这样做。因此,鉴于数据源数组中的元素数量,分配足够容纳所有元素的高度。 - J2theC

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接