UICollectionViewCell 中的 UIImageView 动画不起作用

UIImageView animation inside UICollectionViewCell doesn't work

我有一个 Collection View 有 5 个单元格(页)。

用户在打开 Collection View 时看到的第一页总是欢迎页面,下面有 UIImageView 和 2 个标签。

Collection View 控制器 did load 之后,我想向 UIImageView 添加一个简短的动画,以将其大小从原始大小增加 2。

我是这样尝试的:

  func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    if indexPath.row == 0 {
        guard let cell = collectionView.cellForItem(at: indexPath) as? WelcomeOnboardingCollectionViewCell else { return }
        cell.animate()
    }
}

动画方法如下:

class WelcomeOnboardingCollectionViewCell: UICollectionViewCell {

@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var subtitleLabel: UILabel!

func animate() {
    UIView.animate(withDuration: 3, delay: 0, options: .curveEaseInOut) {
        self.imageView.transform = CGAffineTransform(scaleX: 2, y: 2)
    }
}
}

但是动画没有发生,我只看到最初的小 UIImageView,尽管 print(cell) 正在工作,所以调用了该方法。

我也尝试在 cellForItemAt 中调用 cell.animate(),但后来我看到已经增加了 UIImageView 而没有动画并且在 [=27= 中设置了哪个动画持续时间无关紧要]方法。

还尝试调用 scrollViewDidScroll 中的下一个代码,但没有成功:

collectionView.visibleCells.forEach { ([=12=] as? WelcomeOnboardingCollectionViewCell)?.animate() }

还尝试调用单元格 layoutIfNeeded(),但它没有任何改变。

我错过了什么?

想要的结果:CLICK

Duncan 建议后的工作代码:

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    if indexPath.item == 0 {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "WelcomeOnboardingCell", for: indexPath) as! WelcomeOnboardingCollectionViewCell
        
        cell.imageView.image = UIImage(named: "\(slides[indexPath.row].imageName)")
        cell.titleLabel.text = slides[indexPath.row].title
        cell.subtitleLabel.text = slides[indexPath.row].subtitle
        cell.animationPending = true
        return cell
   }

和 CollectionViewCell class:

class WelcomeOnboardingCollectionViewCell: UICollectionViewCell {

@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var subtitleLabel: UILabel!

var animationPending = false

override func didMoveToSuperview() {
    if animationPending {
        DispatchQueue.main.async {
            self.animate()
        }
    }
    animationPending = false
}

private func animate() {
    UIView.animate(withDuration: 0.3, delay: 0.4, options: .curveEaseInOut) {
        self.imageView.transform = CGAffineTransform(scaleX: 2.3, y: 2.3)
        self.imageView.alpha = 1.0
    }
}
}

选择:

在ViewController的viewDidAppear()中调用animate():

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    collectionView.visibleCells.forEach { ([=15=] as? WelcomeOnboardingCollectionViewCell)?.animate() }
}

在将单元格添加到视图层次结构之前,将调用 collectionView(_:willDisplay:forItemAt:) 方法和 collectionView(_:cellForItemAt:) 方法。在视图成为视图层次结构的一部分之前,您无法触发视图的动画。

我建议将动画“smarts”添加到您的 UICollectionViewCell 子类(或添加到您放在集合视图单元格中的内容视图。

让您的 collectionView(_:cellForItemAt:) 将您手机上的“animationPending”属性 设置为 true。

然后让您的 UICollectionViewCell 通过检查它的“animationPending”标志来响应 didMoveToSuperview() 调用。如果是,运行 你的动画代码并将标志设置回 false。