我正在构建嵌入在容器中的tableView叠加层。 主要目标是使tableView动画化其高度以使其适合屏幕上的内容。 经过长时间的试验和错误,我发现了以下但很棘手的方法:
1)当dataSource更改时,重新加载tableView。
2)更新viewDidLayoutSubviews()
中的tableView的高度约束
3)在动画关闭时调用layoutIfNeeded()
。
4)设置回调容器的高度。
class VC: UIViewController {
let tableView = UITableView()
// This callback is used to updater overlayContainerView height to match tableView's contentSize height.
public var layoutCallback: (_ value: CGFloat)->() = { _ in }
var dataSource: ModalCardOverlayDataSource? = nil { didSet {
tableView.dataSource = dataSource
self.tableView.reloadData()
view.setNeedsLayout()
}
.
.
.
.
override public func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.tableView.snp.updateConstraints { make in
make.height.equalTo(self.tableView.contentSize.height)
}
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
})
layoutCallback(tableView.contentSize.height)
}
}
}
该解决方案效果很好,但有一个缺点:每当高度保持不变时,视图就会向下动画,然后再次刷新时返回正确的高度。
当我删除动画代码时,不会发生此问题。我想这是UIKit固有的问题。
潜在的简便解决方法是引入其他变量来跟踪tableview的高度,当其保持不变时,将跳过动画代码。 但我想了解导致此问题的原因。
override public func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("the height is \(self.tableView.contentSize.height)")
self.tableView.snp.updateConstraints { make in
make.height.equalTo(self.tableView.contentSize.height)
}
UIView.animate(withDuration: 0.3, animations: {
print("the height in animation is \(self.tableView.contentSize.height)")
self.view.layoutIfNeeded()
})
print("the height in CALLBACK is \(self.tableView.contentSize.height)")
layoutCallback(tableView.contentSize.height)
}
当我在刷新具有相同内容的数据源时打印内容视图高度时,这就是我所得到的
初始值
高度为132.0动画中的高度为132.0高度为 132.0在动画中的高度是132.0在CALLBACK中的高度是275.33333587646484在CALLBACK中的高度是275.33333587646484在动画中的高度是275.33333587646484 275.33333587646484高度为275.3333333333333动画中的高度为275.3333333333333高度为275.3333333333333 动画中的高度为275.3333333333333回调中的高度为 275.3333333333333 CALLBACK中的高度为275.3333333333333 CALLBACK中的高度为275.3333333333333
第一次刷新:
高度为132.0动画中的高度为132.0高度为 132.0在动画中的高度是132.0在CALLBACK中的高度是275.33333587646484在CALLBACK中的高度是275.33333587646484
第二次刷新
高度为132.0,动画中的高度为132.0 CALLBACK是132.0的高度是275.33333587646484 动画是275.33333587646484高度是275.3333333333333的 动画中的高度为275.3333333333333,高度为 275.3333333333333动画中的高度为275.3333333333333 CALLBACK中的高度为275.3333333333333 CALLBACK中的高度为 275.3333333333333 CALLBACK中的高度为275.3333333333333高度为275.3333333333333动画中的高度为 275.3333333333333 CALLBACK中的高度为275.3333333333333
任何想法都可能导致这种奇怪的行为吗? 为什么动画代码根据重载是偶数还是奇数来使它在两个高度状态之间切换?
答案 0 :(得分:0)
您需要创建表视图的子类,并在StoryBoard中使用自动布局。内部子类:-
import UIKit
class SelfSizingTableView: UITableView {
override var intrinsicContentSize: CGSize {
self.layoutIfNeeded()
return self.contentSize
}
override var contentSize: CGSize {
didSet{
self.invalidateIntrinsicContentSize()
}
}
}
,还将tableview rowHeight设置为UITableViewAutomaticDimension。