动画 UICollectionView 框架时的布局和单元格问题

问题描述 投票:0回答:2

我面临着一个非常奇怪的问题。我不太喜欢一些高级集合视图布局的东西,但我仍然认为这有点令人困惑。


通过动画应用帧更新(特别是高度更改)使得集合视图(右侧带有红色单元格)在将高度设置为较低值时立即刷新即将关闭的单元格。对

UICollectionView

(左侧有黄色单元格)执行相同的更改效果非常好。请参阅此 Playground 示例进行演示:


UITableView

我希望它首先能够发挥作用,因为表格视图不受此问题的影响。

我已经尝试使用覆盖的流程布局并且:

设置
    import UIKit import PlaygroundSupport class MyViewController : UIViewController, UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate, UICollectionViewDataSource { var col : UICollectionView? func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 50 } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 50 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let c = UITableViewCell() c.textLabel?.text = "cell" c.contentView.backgroundColor = UIColor.yellow return c } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 50 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let c = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) c.contentView.backgroundColor = UIColor.red return c } func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { // print(Thread.callStackSymbols.joined(separator: "\n") + "\n\n") } override func loadView() { let view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300)) view.backgroundColor = .white var f = view.bounds f.size.height = 300 let holder = UIView(frame: view.bounds) holder.autoresizingMask = [.flexibleWidth] f.size.width = 150 f.size.height = view.frame.size.height let table = UITableView(frame: f, style: .plain) table.delegate = self table.dataSource = self table.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleRightMargin] f.origin.x = 150 let layout = UICollectionViewFlowLayout() layout.itemSize = CGSize(width: 150, height: 50) layout.minimumInteritemSpacing = 0 layout.sectionInset = UIEdgeInsets.zero layout.minimumLineSpacing = 1 let collection = UICollectionView(frame: f, collectionViewLayout: layout) collection.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell") collection.delegate = self collection.dataSource = self collection.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleLeftMargin] col = collection view.addSubview(holder) holder.addSubview(table) holder.addSubview(collection) self.view = view } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) toggleContent() } func toggleContent() { guard let v = self.view.subviews.first else { return } var f = v.frame f.size.height = (f.size.height == 300) ? 150:300 UIView.animate(withDuration: 1.0) { v.frame = f } DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.5) { self.toggleContent() } } } PlaygroundPage.current.liveView = MyViewController()
  • 方法返回
    shouldInvalidateLayout
    (测试为当单元格即将消失时命中),这样我就可以稍后处理手动失效
    扩展 
  • false
  •  的矩形
    
    压倒一切
  • layoutAttributesForElements(in:)
  • 
    
    
  • 没有任何影响。
finalLayoutAttributesForDisappearingItem

中注释掉的

print()
显示无论如何都会调用单元格被解雇的
collectionView(_:didEndDisplaying:)

动机:这是由此引起的现实问题:

我想可能有一个非常简单、正确的解决方案?我更喜欢它而不是任何“极其黑客”的东西。

请让我们继续修复 Playground 示例,不要猜测! ;)

ios uicollectionview uicollectionviewcell uiviewanimation uicollectionviewlayout
2个回答
1
投票
layoutSubviews

,如下所示:


layoutIfNeeded()

看看它是否有效:/


0
投票

UIView.animate(withDuration: 1.0) { v.frame = f self.view.layoutIfNeeded() }

© www.soinside.com 2019 - 2024. All rights reserved.