Ios collectionView.collectionViewLayout.invalidateLayout()
我在TableView中有一个DynamicCollectionView,当我添加Ios collectionView.collectionViewLayout.invalidateLayout(),ios,swift,uicollectionview,uikit,Ios,Swift,Uicollectionview,Uikit,我在TableView中有一个DynamicCollectionView,当我添加invalidateLayout时出现了一个bug(下图) 但是如果我删除了invalidateLayout前四个单元格,并且布局没有正确显示,则 请帮助我搜索了整个堆栈,但没有任何帮助,谢谢 如果你需要测试 主视图控制器 class ViewController: UIViewController, UIScrollViewDelegate { override func viewDidLoad() {
invalidateLayout
时出现了一个bug(下图)
但是如果我删除了invalidateLayout
前四个单元格,并且布局没有正确显示,则
请帮助我搜索了整个堆栈,但没有任何帮助,谢谢
如果你需要测试
主视图控制器
class ViewController: UIViewController, UIScrollViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
setting()
}
func setting(){
getData()
tableView.dataSource = self
tableView.delegate = self
tableView.estimatedRowHeight = UITableView.automaticDimension
tableView.rowHeight = UITableView.automaticDimension
}
//load data
func pagination(_ completion: (()->())?){
SmartNetworkSevrice.getGoods(with: url) { [unowned self] (data) in
guard data.modals.count > 0 else {
self.tableView.tableFooterView = nil
return
}
self.goods.append(contentsOf: data.modals)
self.offSet += data.modals.count
DispatchQueue.main.async {
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.tableFooterView = nil
if self.goods.count == data.modals.count || self.isRefresh {
self.tableView.reloadRows(at: [indexPath], with: .none)
} else {
if let cell = self.tableView.cellForRow(at: indexPath) as? TVCellGoods {
UIView.performWithoutAnimation {
self.tableView.beginUpdates()
cell.insertGoods(data.modals)
cell.layoutIfNeeded()
cell.collectionViewHeight.constant = cell.collectionView.collectionViewLayout.collectionViewContentSize.height
self.tableView.endUpdates()
}
}
}
completion?()
}
}
// define bottom of tableView
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard scrollView == self.tableView else { return }
if (!isMoreDataLoading) {
// Вычислить позицию длины экрана до нижней части результатов
let scrollViewContentHeight = scrollView.contentSize.height
let scrollOffsetThreshold = scrollViewContentHeight - scrollView.bounds.size.height
if(scrollView.contentOffset.y > scrollOffsetThreshold && scrollView.isDragging) {
isMoreDataLoading = true
self.tableView.isScrollEnabled = false;
self.tableView.isScrollEnabled = true;
pagination(nil)
}
}
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "goods", for: indexPath) as? TVCellGoods else { return UITableViewCell() }
guard bestGoods.count != 0, goods.count != 0 else { return UITableViewCell() }
cell.delegate = self
cell.configure(bestGoods, goods, categories)
// автообновление высоты
self.tableView.beginUpdates()
cell.collectionViewHeight.constant = cell.collectionView.collectionViewLayout.collectionViewContentSize.height
self.tableView.endUpdates()
return cell
}
}
extension ViewController: UITableViewDelegate, CallDelegate {
func callMethod() {}
func callMethod(push vc:UIViewController) {
self.navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
带有collectionView的TableViewCell
class TVCellGoods: UITableViewCell {
@IBOutlet weak var collectionView:UICollectionView!
@IBOutlet weak var collectionViewHeight:NSLayoutConstraint!
weak var delegate:CallDelegate?
var bestGoods = [Goods]() // лучшие товары
var goods = [Goods]() // все товары
var categories = [Menu]()
override func layoutSubviews() {
super.layoutSubviews()
self.collectionView.collectionViewLayout.invalidateLayout()
}
override func awakeFromNib() {
super.awakeFromNib()
collectionView.delegate = self
collectionView.dataSource = self
collectionView.tag = 2
collectionView.isScrollEnabled = false
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func configure(_ best:[Goods],_ goods:[Goods], _ category:[Menu]) {
self.bestGoods = best
self.goods = goods
self.categories = category
self.collectionView.reloadData()
}
func insertGoods(_ data:[Goods]) {
self.goods.append(contentsOf: data)
let count = self.bestGoods.count + self.categories.count + self.goods.count
let indexPaths = ((count - data.count) ..< count)
.map { IndexPath(row: $0, section: 0) }
self.collectionView.performBatchUpdates({
self.collectionView.insertItems(at: indexPaths)
}, completion: nil)
}
}
编辑
如果我使用
self.collectionView.performBatchUpdates({
self.collectionView.insertItems(at: indexPaths)
}, completion: { _ in
self.collectionView.reloadItems(at: indexPaths)
})
使用invalidateLayout
之后,我在屏幕底部得到一个空白
但如果我删除invalidateLayout
我会得到错误的布局
如果你没有像我一样的项目,那么放弃你的改进项目
第二次编辑
我注意到iPhone11Pro上有一个缩进,iPhone11Pro Max上的一切都很好
更新:我在iPhone SE、11和11 Max的模拟器上验证了这一点,在集合视图的末尾没有死区 我的模拟器设置为暗模式,以显示集合视图的底部刚好够加载图标 我不得不做一些修改,使它的尺寸合适。首先,我更改了
TVCellGoods
类中的insertGoods
函数,以在插入后仅重新加载新添加的项,并且在列表顶部不再有缺少的项:
self.collectionView.performBatchUpdates({
self.collectionView.insertItems(at: indexPaths)
}, completion: { _ in
self.collectionView.reloadItems(at: indexPaths)
})
一个大问题是设置tableView单元格的估计行高。我已删除了estimatedHeightForRowAt
覆盖,并将您的heightForRowAt
替换为:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
return (tableView.frame.width / 2.5) + 20
} else if indexPath.row == 1 {
return 70
} else {
guard let cell = tableView.cellForRow(at: indexPath) as? TVCellGoods else { return UITableView.automaticDimension }
// print(cell.collectionViewHeight.constant)
return cell.collectionViewHeight.constant
}
}
我还必须将layoutIfNeeded
添加到您的ViewController UITableViewDataSource
扩展名中的cellForRow中:
self.tableView.beginUpdates()
cell.collectionViewHeight.constant = cell.collectionView.collectionViewLayout.collectionViewContentSize.height
self.tableView.endUpdates()
cell.collectionView.layoutIfNeeded()
self.tableView.layoutIfNeeded()
最后,我必须更新您的布局子视图
,以便在TVCellGoods
中使布局无效后分配正确的高度:
override func layoutSubviews() {
super.layoutSubviews()
self.collectionView.collectionViewLayout.invalidateLayout()
self.collectionViewHeight.constant = self.collectionView.collectionViewLayout.collectionViewContentSize.height
}
以下是更新的源代码:
评论不用于扩展讨论;此对话已结束。请检查我的更新答案,然后再试一次。它应该能解决你的布局问题。
override func layoutSubviews() {
super.layoutSubviews()
self.collectionView.collectionViewLayout.invalidateLayout()
self.collectionViewHeight.constant = self.collectionView.collectionViewLayout.collectionViewContentSize.height
}