在 ScrollView 内更新子视图的高度(没有滚动的 UITableView)后 UIStackView 不更新
UIStackView not updating after updating height of subview (UITableView with no scroll) while inside a ScrollView
当 stackView 在滚动视图中时,如何使 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 关于非滚动 tableView)但是 UIStackView 没有堆叠 UITableView。
UIView D
堆叠在 UIView C
下面
UITableView X
和 UITableView Y
也堆叠在 UIView B
下面
我的猜测是我需要使 stackview 无效,或者以某种方式让它重新分配它的子视图。我该怎么做?
首先,警告:
您要实现的并不是真正标准的 iOS 行为。您应该首先考虑一种不同的方法,例如创建具有多个部分的单个分组 table 视图。您可以在 table 视图中将自定义视图实现为节页眉或页脚。
现在,如果您真的想采用原来的方法...
...出于某些重要原因,您应该知道 table 视图在默认情况下没有固有的内容大小。因此,您需要告诉 table 视图它应该有多高,否则它只会缩小到零高度。
您可以通过继承 UITableView
并覆盖其 intrinsicContentSize()
来实现此目的,正如 Rob 在 this answer 中对类似问题所建议的那样。
或者您为每个 table 视图添加高度限制并在代码中动态设置它们的常量。一个简单的例子:
- 将您的 table 视图添加到 Interface Builder 中的垂直堆栈视图。
- 为两个 table 视图提供前导和尾随约束,以将它们的左右边缘固定到堆栈视图。
在相应的视图控制器中为您的 table 视图创建出口:
@IBOutlet weak var tableView1: UITableView!
@IBOutlet weak var tableView2: UITableView!
@IBOutlet weak var tableView1HeightConstraint: NSLayoutConstraint!
@IBOutlet weak var tableView2HeightConstraint: NSLayoutConstraint!
覆盖该视图控制器的 updateViewConstraints()
方法:
override func updateViewConstraints() {
super.updateViewConstraints()
tableView1HeightConstraint.constant = tableView1.contentSize.height
tableView2HeightConstraint.constant = tableView2.contentSize.height
}
现在,每当您的任何 table 视图的内容发生变化时(例如,当您添加或删除行或更改单元格内容时),您需要告诉您的视图控制器它需要更新其约束。假设您有一个按钮,每次点击它都会向 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()
}
tl;博士:
A UITableView
不适合在未启用滚动的情况下使用,因此您始终需要在其内容更改时明确设置其高度 - 可能是使用约束或通过覆盖 table 视图内在内容大小。
当 stackView 在滚动视图中时,如何使 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 关于非滚动 tableView)但是 UIStackView 没有堆叠 UITableView。
UIView D
堆叠在UIView C
下面
UITableView X
和UITableView Y
也堆叠在UIView B
下面
我的猜测是我需要使 stackview 无效,或者以某种方式让它重新分配它的子视图。我该怎么做?
首先,警告:
您要实现的并不是真正标准的 iOS 行为。您应该首先考虑一种不同的方法,例如创建具有多个部分的单个分组 table 视图。您可以在 table 视图中将自定义视图实现为节页眉或页脚。
现在,如果您真的想采用原来的方法...
...出于某些重要原因,您应该知道 table 视图在默认情况下没有固有的内容大小。因此,您需要告诉 table 视图它应该有多高,否则它只会缩小到零高度。
您可以通过继承 UITableView
并覆盖其 intrinsicContentSize()
来实现此目的,正如 Rob 在 this answer 中对类似问题所建议的那样。
或者您为每个 table 视图添加高度限制并在代码中动态设置它们的常量。一个简单的例子:
- 将您的 table 视图添加到 Interface Builder 中的垂直堆栈视图。
- 为两个 table 视图提供前导和尾随约束,以将它们的左右边缘固定到堆栈视图。
在相应的视图控制器中为您的 table 视图创建出口:
@IBOutlet weak var tableView1: UITableView! @IBOutlet weak var tableView2: UITableView! @IBOutlet weak var tableView1HeightConstraint: NSLayoutConstraint! @IBOutlet weak var tableView2HeightConstraint: NSLayoutConstraint!
覆盖该视图控制器的
updateViewConstraints()
方法:override func updateViewConstraints() { super.updateViewConstraints() tableView1HeightConstraint.constant = tableView1.contentSize.height tableView2HeightConstraint.constant = tableView2.contentSize.height }
现在,每当您的任何 table 视图的内容发生变化时(例如,当您添加或删除行或更改单元格内容时),您需要告诉您的视图控制器它需要更新其约束。假设您有一个按钮,每次点击它都会向
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() }
tl;博士:
A UITableView
不适合在未启用滚动的情况下使用,因此您始终需要在其内容更改时明确设置其高度 - 可能是使用约束或通过覆盖 table 视图内在内容大小。