在 UICollectionView 中,折叠动画不完善,隐藏项没有高度收缩动画

In UICollectionView, collapse animation is imperfect, with no height shrinking animation for the hidden item

基于

中描述的问题

以及

中提到的改进

我进行了以下更改

  1. 添加了内部 UIView,用于折叠和展开目的
  2. 内部 UIView 将属性 Clips to Bounds 设置为 true
  3. 垂直 UIStackView 放置在内部 UIView,底部约束设置为 high
  4. 我真的不知道。出于未知原因,父级 UIStackView 的底部约束需要 low,以便 UI 在折叠动画期间保持在顶部。

这是我的结果。


如您所见,

  1. 展开动画效果很好!
  2. 对于折叠动画,里面的UIView会立即消失,没有任何动画。

你有什么想法,为什么在崩溃时没有隐藏动画?

这是执行折叠/展开的代码。

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return shops.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let collectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? CollectionViewCell else {
            fatalError()
        }
        
        let shop = shops[indexPath.item]
        
        collectionViewCell.title.text = shop.title
        collectionViewCell._description.text = shop.description
        
        if isExpanded[indexPath.item] {
            collectionViewCell.innerView.isHidden = false
        } else {
            collectionViewCell.innerView.isHidden = true
        }
        
        return collectionViewCell
    }

}
extension ViewController: UICollectionViewDelegate {
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        for i in (0..<isExpanded.count) {
            if i == indexPath.item {
                // ensure always visible
                isExpanded[i] = true
            } else {
                // set all other rows to false
                isExpanded[i] = false
            }
            if let c = collectionView.cellForItem(at: IndexPath(item: i, section: 0)) as? CollectionViewCell {
                c.innerView.isHidden = !isExpanded[i]
            }
        }
        collectionView.performBatchUpdates(nil, completion: nil)
    }
}

目前我试过的是

  1. 使用零高度约束来激活/停用,以替换 isHidden
  2. 使用UIView.animate

但是,里面的UIView会立即消失,没有任何缩高动画。

你知道我该如何解决这个问题吗?谢谢。

这是说明问题的代码 - https://github.com/yccheok/shop-dialog/tree/c399bca163096ad27de7de866af5d2de370a8afb

正如我在对另一个问题的评论中提到的,我们很少能找到“一刀切”的解决方案。

在堆栈视图的排列子视图上设置 .isHidden 时,不是与默认行为作斗争,这里有一个不同的方法。

使用两个底约束:

  • 从“顶部/always-visible”的底部开始UI个元素
  • “show/hide”元素底部的一个(它们的容器视图)

second 约束的 .priority 设置为 750 (.defaultHigh).

当您希望单元格“折叠”时,将 第一个 约束的 .priority 设置为 751 (.defaultHigh + 1)。

当您希望“扩展”单元格时,将 第一个 约束的 .priority 设置为 749 (.defaultHigh - 1)。

要为 expand/collapse 效果设置动画,请将 performBatchUpdates 包裹在 UIView.animate 块中。

我在此处分叉了您的 GitHub 存储库 - https://github.com/DonMag/shop-dialog - 并将此方法添加为“V2”,以便您可以检查它并查看差异。