gpt4 book ai didi

ios - collectionView.collectionViewLayout.invalidateLayout()

转载 作者:行者123 更新时间:2023-12-01 16:12:26 28 4
gpt4 key购买 nike

我在 TableView 中有一个动态 collectionView,当我添加 invalidateLayout 时出现错误(图片如下)但是如果我删除 invalidateLayout 前四个单元格被隐藏并且布局显示不正确,video

请帮助我搜索了整个堆栈,但没有任何帮助,谢谢

如果你需要测试project

主视图 Controller

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)

}

}

和 CollectionViewCell

class CVCellGoods: UICollectionViewCell {

@IBOutlet weak var bgView: UIView!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var title: UILabel!
@IBOutlet weak var price: UILabel!
@IBOutlet weak var delivery: UIImageView!
@IBOutlet weak var premium: UIImageView!

override func prepareForReuse() {
super.prepareForReuse()
delivery.image = nil
premium.image = nil
title.text = nil
price.text = nil
imageView.image = nil
imageView.sd_cancelCurrentImageLoad()
}

override func awakeFromNib() {
super.awakeFromNib()

imageView.backgroundColor = UIColor(red: 215/255, green: 215/255, blue: 215/255, alpha: 1)

self.contentView.layer.cornerRadius = 5
self.contentView.layer.masksToBounds = true

self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 0, height: 0.5)
self.layer.shadowRadius = 1
self.layer.shadowOpacity = 0.3
self.layer.masksToBounds = false
self.layer.shouldRasterize = true
self.layer.rasterizationScale = UIScreen.main.scale

}

}

编辑

如果我用

    self.collectionView.performBatchUpdates({
self.collectionView.insertItems(at: indexPaths)
}, completion: { _ in
self.collectionView.reloadItems(at: indexPaths)
})

使用 invalidateLayout 然后我在屏幕底部得到一个空白区域 screen但是如果我删除 invalidateLayout 我会得到错误的布局 Layout

如果你没有像我的那样,然后放弃你改进的项目

第二次编辑

我注意到 iPhone 11 Pro 上有一个凹痕,在 iPhone 11 Pro Max 上一切正常

iPhone 11 Pro IOS 13.3

iPhone 11 Pro Max IOS 13.3

最佳答案

更新:我在 iPhone SE、11 和 11 Max 的模拟器上验证了它在 Collection View 末尾没有死角的情况。

My simulator is set to dark mode to show that the bottom of the collection view is just enough for the loading icon.

enter image description here

我必须对其进行一些更改才能使其大小合适。首先,我更改了 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 中的布局无效后,我必须更新您的 layoutSubviews 以分配正确的高度:

override func layoutSubviews() {
super.layoutSubviews()

self.collectionView.collectionViewLayout.invalidateLayout()

self.collectionViewHeight.constant = self.collectionView.collectionViewLayout.collectionViewContentSize.height
}

Here is the updated source code: https://drive.google.com/open?id=1ldr4Ml2prZKmr1C4i1s5Sg7LvvxL7-jO

关于ios - collectionView.collectionViewLayout.invalidateLayout(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61481436/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com