动画是集合视图单元格内 imageView 的突出显示状态

Animate isHighlighted state of an imageView inside a cell of a collection view

我遇到了集合视图单元格内 imageView 状态的 isHighlighted 问题:我无法按照我的目标设置 2 个图像之间的过渡动​​画。

我的集合视图的每个自定义单元格都有 3 个视图:

  1. 一个 UIImageView : 一个背景图片,带有高亮和非高亮相关的 .png
  2. 第二个 UIImageView : 另一个带有高亮和非高亮相关 .png 的图像作为前一个 UIImageView
  3. 的子视图
  4. 自定义 UILabel:文本标签

当我触摸单元格时,两个 ImageView 立即移动到突出显示状态,但我希望它们转换到该状态(一个简单的 CrossDissolve 转换)

我尝试了两种不同的方法:覆盖自定义单元格中的 isSelected 方法 class 并将动画放入 collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)

覆盖已选中 属性:

    override var isSelected: Bool {
        didSet {
            UIView.transition(with: cellImageView, duration: 1, options: .transitionCrossDissolve, animations: {
                self.cellImageView.setNeedsLayout()
                self.cellImageView.layoutIfNeeded()
                self.cellImageView.isHighlighted = self.isSelected
            })
        }
    }

通过这种方式,当我在模拟器中点击单元格时,无论是单元格被选中还是失去选中状态,我都看不到任何动画,除非我 单击并按住一个单元格:然后我得到一个动画,显示前一个单元格丢失了它的选定单元格(换句话说,我将先前选定的 imageView 从 isHighlighted(true) 过渡到 isHighlighted(false)).

didSelectItemAt indexPath 方法

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        let cell = collectionView.cellForItem(at: indexPath) as! SubMenuCell
        UIView.transition(with: cell, duration: 1.0, options: .transitionCrossDissolve, animations: 
            cell.setNeedsLayout()
            cell.layoutIfNeeded()
            cell.cellImageView.isHighlighted = cell.isSelected
        })
    }

此方法不会在单元格被选中时触发动画,但会在单元格从 isSelected(true) 移动到 isSelected(false) 时提供过渡动画:换句话说,我看到了上一个选定的单元格淡出,我没有看到选定的单元格淡入

如能提供有关它为何不起作用以及如何修复的任何提示,我将不胜感激!

感谢大家花时间阅读和回复! 最好的,

我不确定,但我认为您可能还想覆盖;

override func setSelected(_ highlighted: Bool, animated: Bool)

在您的 UICollectionViewCell 以及 isSelected 属性 中,因此您的动画代码在 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath).

*请注意,isHighlightedisSelected 之间也存在差异,您在问题中说 isHighlighted,但在您的实施中利用了 isSelected

感谢大家花时间思考我的问题。 通过进一步调查,我决定检查 3 个事件是如何以及何时触发的,即 cell.isHighlightedcell.isSelectedcollectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath),实际上我发现了一些非常有趣的事情。让我总结一下:

当您触摸集合视图中的单元格 (cell1) 时,似乎会发生以下事件:

  1. cell1.isHightlighted 设置为 true
  2. cell1.isHightlighted 设置为 false
  3. cell1.isSelected设置为true,回调cell1.isHighlighted属性
  4. 最后 collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 方法被调用

现在,当您触摸集合视图中的另一个单元格 (cell2) 时,会发生以下事件:

  1. cell2.isHighlighted 设置为 true
  2. cell1.isSelected设置为false,回调cell1.isHightlighted属性
  3. cell2.isHighlighted 设置为 false
  4. cell1.isSelected 再次设置为 false (!)
  5. cell2.isSelected设置为true,回调cell2.isHighlighted属性
  6. 最后 collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 方法是 叫

考虑到这一点,我得出的结论是 运行 集合视图方法中 isHighlighted 状态的过渡动画永远不会按预期工作,因为 属性 已经在到达方法之前已经设置。

我发现获得两个动画(isHighlighted truefalse)的一个解决方案是作用于 isHighlighted 的 属性 观察者和我的自定义集合视图单元格的 isSelected,如下所示:

override var isHighlighted: Bool {
        willSet {
            if newValue == true {
                UIView.transition(with: cellImageView, duration: 1.0, options: .transitionCrossDissolve, animations: {
                    self.cellImageView.isHighlighted = newValue
                })
            }
        }
    }
    
 override var isSelected: Bool {
        willSet {
            if newValue == false {
                UIView.transition(with: cellImageView, duration: 1.0, options: .transitionCrossDissolve, animations: {
                    self.cellImageView.isHighlighted = newValue
                })
            }
        }
    }

希望对您有所帮助,再次感谢所有花了一些时间试图弄明白的人! 如果有人找到更优雅的解决方案,请不要犹豫post吧!!! 最好的,