我有一个
UIStackView
,它可以根据用户选择显示标签、图像、表格视图或任何内容。这是我当前的动态视图层次结构:
当我使用标签或图像调用
UIStackView_Child.addArrangedSubview(...)
时,它工作正常,但 addArrangedSubview(tableView)
不显示表格。我有 tableView.scrollEnabled = false
并根据单元格数量将框架设置为固定高度,并定义了表格的 cellHeight
。
任何帮助将不胜感激,谢谢!
在不显式设置框架高度和宽度的情况下执行此操作的另一种方法是将表格视图嵌入到空视图中,将表格视图固定到顶部、底部、左侧和右侧,并设置“大于或等于”约束表格视图的高度。
那是因为 stackview 试图尽可能地压缩内容。当您最初添加表视图时,我假设它没有内容,因此 stackview 将宽度压缩为 0,因为它没有任何内容可显示。您必须执行以下两件事之一:
表格填充数据后,您必须设置tableView的框架。我通过计算每个单元格的大小来做到这一点。我知道宽度将与包含 stackview 的视图一样大。所以它最终会变成这样
let estimatedHeight = tableView.numberOfRows(inSection: 0) //You may need to modify as necessary
let width = parentView.frame.size.width
tableView.frame = CGRect(x: 0, y: 0, width: width, height: estimatedHeight)
一旦设置了 tableView 的框架,stackview 就会自动调整。
您还可以使用Combine自动监控UITableView的高度:
import Combine
var tableViewHeightConstraint: NSLayoutConstraint?
var cancellables: Set<AnyCancellable> = []
// Table View Content Size monitor
tableView.publisher(for: \.contentSize)
.receive(on: DispatchQueue.main)
.sink { self.tableViewHeightConstraint?.constant = $0.height }
.store(in: &cancellables)
或者,如果您没有可用的联合收割机,您可以添加观察员:
tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if(keyPath == "contentSize") {
// Here you could get from change or simple get it directly from the table view
tableViewHeightConstraint?.constant = tableView.contentSize.height
}
}
您可以使用RxSwift观察UITableView的内容大小:
// in UIViewController
import RxSwift
@IBOutlet var tableViewHeightConstraint: NSLayoutConstraint!
override public func viewDidLoad() {
super.viewDidLoad()
// subscribe to observe table view content size
tableView.rx.observe(CGSize.self, "contentSize")
.subscribe(onNext: { [weak self] newSize in
guard let self,
let height = newSize?.height
else {
return
}
// adjust table view height constraint
self.tableViewHeightConstraint.constant = height
})
.disposed(by: disposeBag)
}