UICollectionViewCell - 当其内容改变时动画单元格高度改变
Posted
技术标签:
【中文标题】UICollectionViewCell - 当其内容改变时动画单元格高度改变【英文标题】:UICollectionViewCell - animate cell height change when its content changes 【发布时间】:2020-06-17 14:18:01 【问题描述】:我有一个非常简单的UICollectionView
,使用 ios 13 的UICollectionViewCompositionalLayout
。单元格有一个垂直的UIStackView
,当您按下“切换详细信息”按钮时,我只需更改detailsView
的isHidden
值。当单元格然后通知视图控制器它需要执行collectionView.collectionViewLayout.invalidateLayout()
时,基本上一切正常:详细信息视图被打开和关闭。但它没有动画,所以看起来有点刺耳。
class ViewController: UIViewController
@IBOutlet private var collectionView: UICollectionView!
override func viewDidLoad()
super.viewDidLoad()
collectionView.collectionViewLayout = createLayout()
private func createLayout() -> UICollectionViewLayout
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(200))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(200))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = .init(top: 16, leading: 16, bottom: 16, trailing: 16)
section.interGroupSpacing = 16
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
extension ViewController: UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return 10
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.resize = [weak self] in
UIView.animate(withDuration: 2)
self?.collectionView.collectionViewLayout.invalidateLayout()
return cell
class Cell: UICollectionViewCell
@IBOutlet private var detailsView: UIView!
var resize: (() -> Void)?
override func awakeFromNib()
super.awakeFromNib()
contentView.layer.cornerRadius = 10
@IBAction private func toggleDetails()
detailsView.isHidden.toggle()
resize?()
复制项目:https://github.com/kevinrenskers/CellHeight.
如何为这个细节视图的切换设置动画,以便高度变化动画?可以与UIStackView
结合使用并显示/隐藏其子视图吗?请注意,细节视图在现实世界的应用程序中没有固定的高度,所以我不能只在两个固定值之间切换单元格高度。
【问题讨论】:
您使用集合视图而不是表格视图是否有原因? 是的。在真正的应用程序中,我在 collectionview 中也有水平滚动部分,这正是 UICollectionViewCompositionalLayout 的完美之处。 嗯...我在集合视图方面做得很少,部分原因是(我的印象是)管理单元格大小/调整大小非常困难。你可能想看看这个:raywenderlich.com/7246-expanding-cells-in-ios-collection-views——不太一样,但可能会给你一个实现的方向。除非您的经验不同,否则我的方法 - 因为 tableview 单元格展开/折叠非常容易 - 将使用 tableview,根据需要在 tableview 单元格中嵌入“水平滚动”集合视图(评论,而不是解决方案)。 如果你要对单元格的高度进行动画处理(将当前单元格更改为新单元格,甚至使用CGAffineTransform
)然后在动画完成调用invalidateLayout
,那么collectionView 有重新计算项目的大小
我无法让它工作,不。只需在示例项目中尝试它,如果你让它工作就提交它作为答案:)
【参考方案1】:
随着集合视图的动画化,我将您的存储库提供给您并进行一些更改。
https://github.com/lebaotrung93/CellHeight
它有效。但是使用 UIStackView,由于其自身的行为,似乎很难在 CollectionView
中管理它的大小。
【讨论】:
感谢您的回答和代码!但是动画看起来很糟糕,并且您禁用了 UICollectionViewCompositionalLayout 代码。再次启用它仍然可以正常工作,但动画仍然很糟糕:/我会在没有stackview的情况下尝试它。 是的,去掉stackview让动画效果好很多。它会自动调整大小,所以我认为在重新加载时,事件只是一行,其他人仍然调用 reload !!?。【参考方案2】:我相信你应该在动画块之外调用collectionView.collectionViewLayout.invalidateLayout()
,然后在动画块中调用self?.collectionView.layoutIfNeeded()
。
【讨论】:
我其实在上届WWDC期间就这个问题和苹果工程师打过电话,基本上没有解决办法。以上是关于UICollectionViewCell - 当其内容改变时动画单元格高度改变的主要内容,如果未能解决你的问题,请参考以下文章
Swift 检测 UICollectionViewCell 是不是被拖到另一个 UICollectionViewCell 之上