在ScrollView内部更新子视图的高度(没有滚动的UITableView)后,UIStackView不会更新

时间:2016-09-04 22:04:35

标签: ios uitableview swift2 uistackview

当stackView在scrollview中时,如何让UIStackView重新分发它的子UITableViews

我的布局层次结构基于苹果关于Dynamic content for StackViews

的官方文档
 - UISCrollView
   - UIStackView
     - UIView A
     - UIView B
     - UIView C
     - UITableView X
     - UITableView Y
     - UIView D

约束按文档设置。 StackView的初始布局是正确的,显示所有可见的子视图。当强制常规视图扩展到屏幕高度以外时,滚动按预期工作。此外,在故事板中查看布局时,所有内容都按预期堆叠 此时UITableView为空。只要我向tableView添加内容,就会出现问题。

问题
当我通过在它们上面调用.reloadData()来动态更新TableView时,我看到它们的内容出现了。 (thanks to this answer关于非滚动的tableViews)但是 UIStackView没有堆叠UITableViews。

  • UIView D位于UIView C
  • 下方
  • UITableView XUITableView Y也位于UIView B
  • 下方

我的猜测是我需要使stackview无效,或以某种方式让它重新分配它的子视图。我怎么能这样做?

enter image description here

1 个答案:

答案 0 :(得分:5)

首先,警告:

您尝试实现的目标并非真正的标准iOS行为。您应该首先考虑一种不同的方法,例如创建具有多个部分的单个分组表视图。您可以在表视图中实现自定义视图作为节页眉或页脚。

现在,如果你真的想采用你最初的方法......

...出于某些重要原因,您应该注意表格视图默认情况下不具有内在内容大小。因此,您需要告诉表格视图它应该有多高,否则它只会缩小到零高度。

您可以通过子类化UITableView并覆盖其intrinsicContentSize()来实现此目标,正如Rob在this answer中建议的类似问题。

或者为每个表视图添加一个高度约束,并在代码中动态设置它们的常量。一个简单的例子:

  1. 将两个表视图添加到Interface Builder中的垂直堆栈视图。
  2. 为两个表视图提供前导和尾随约束,以将其左右边缘固定到堆栈视图。
  3. 在相应的视图控制器中为表视图创建出口:

    @IBOutlet weak var tableView1: UITableView!
    @IBOutlet weak var tableView2: UITableView!
    
    @IBOutlet weak var tableView1HeightConstraint: NSLayoutConstraint!
    @IBOutlet weak var tableView2HeightConstraint: NSLayoutConstraint! 
    
  4. 覆盖该视图控制器的updateViewConstraints()方法:

    override func updateViewConstraints() {
        super.updateViewConstraints()
        tableView1HeightConstraint.constant = tableView1.contentSize.height
        tableView2HeightConstraint.constant = tableView2.contentSize.height
    }
    
  5. 现在,只要您的任何表视图的内容发生更改(例如,当您添加或删除行或更改单元格内容时),您都需要告诉视图控制器它需要更新其约束。我们假设您有一个按钮,每次点击它时都会向tableView1添加一个单元格。您可以像这样实现其操作:

    @IBAction func buttonTappen(sender: AnyObject) {
        // custom method you implement somewhere else in your view controller
        addRowToTableView1DataSource()
        // reload table view with the updated data source
        tableView1.reloadData()
        // triggers an updateViewConstraints() call
        view.setNeedsUpdateConstraints()
    }
    
  6. TL; DR:

    UITableView不打算在不启用滚动的情况下使用,因此您需要在其内容更改时明确设置其高度 - 可能是使用约束还是覆盖表格视图&#39}内在的内容大小。