在集合视图单元格中使用淡入效果动画图像

4
注意:我已经尝试了所有在stackoverflow上匹配的问题,但都没有帮助解决这个问题/场景,因此现在发帖求助。
我有一个集合视图,其中有许多单元格,每个单元格都有一个图像视图。每个单元格将具有不同的图像数组,我需要通过淡入淡出效果一个接一个地显示它们。第一次显示时显示正确,但滚动后就会出现问题。第一个单元格的图像会显示在其他任何单元格中。图像会混乱。

extension ViewController: UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imagesArray.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath)
//        let image = cell.viewWithTag(1) as! UIImageView
//        let imgArr =  imagesArray[indexPath.row]
//        image.downloadImageAndAnimateIt(imageStringArray: imgArr)
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let size = self.collectionView.bounds.size.width / 2 - 5
        return CGSize(width: size, height: size - 5)
    }

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        let image = cell.viewWithTag(1) as! UIImageView
        let imgArr =  imagesArray[indexPath.row]
        image.downloadImageAndAnimateIt(imageStringArray: imgArr)

    }


}
//=========== END of view controller

extension UIImageView {

    func downloadImageAndAnimateIt(imageStringArray:[String]){

        var imagesArray = [UIImage]()
        for imgStr in imageStringArray{
            imagesArray.append(UIImage(named: imgStr)!)
        }        

        let dispatchGroup = DispatchGroup()
//        dispatchGroup.notify(queue: DispatchQueue.main) {[weak self] in
//            self?.animationImages = imagesArray.compactMap({$0})
//            self?.animationDuration = 5.0
//            self?.startAnimating()
//        }

        var photoCount = 0        
        var timer = Timer()

        dispatchGroup.notify(queue: DispatchQueue.main) {[weak self] in

            timer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true, block: { (timer) in
                if (photoCount < imagesArray.count - 1){
                    photoCount = photoCount + 1;
                }else{
                    photoCount = 0;
                }
                if let this = self {
                    UIView.transition(with: this, duration: 2.0, options: .transitionCrossDissolve, animations: {
                        this.image = imagesArray[photoCount]
                    }, completion: nil)
                }
            })

        }

    }

}

图片不应该随着滚动而移动,它们应该保持在原来的单元格中。


在下载图像之前,将image.image设置为nil。 - Jaydeep Vyas
嗨Jaydeep,感谢您的回复。 我已经完成了一个演示项目,在其中使用了来自资产的图像并执行动画。尝试了您的解决方案,但问题仍然存在。 - Kamini Sharma
你能否将演示项目上传到Dropbox并在此处分享链接? - Jaydeep Vyas
请查看以下演示项目的链接: https://drive.google.com/open?id=1yJjLLh3-WFuVnytfbxfVVvuJZ4VBRVzj - Kamini Sharma
抱歉回复晚了,我认为问题在于ImageView扩展。请尝试我下面回答的代码,我已经测试过了,代码不会打乱图像。 - Jaydeep Vyas
3个回答

2
你需要创建CustomCollectionCell类来分离你的代码,可以尝试以下方式,对于下载图片,你可以使用SDWebImage。最初的回答。
extension ViewController: UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imagesArray.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! CollectionViewCell

        cell.imgView.image = nil
        cell.createImages(imageStringArray: imagesArray[indexPath.row])
        cell.configureTimer()
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let size = self.collectionView.bounds.size.width / 2 - 5
        return CGSize(width: size, height: (size * 1.5) - 5)
    }



}

class CollectionViewCell: UICollectionViewCell {

    override func awakeFromNib()
    {
        super.awakeFromNib()
        // Initialization code

    }
    var imageArray:[UIImage] = []
    var timer = Timer()
    var photoCount: Int = 0
    @IBOutlet weak var imgView: UIImageView!
    func createImages(imageStringArray:[String])
    {
        self.imageArray.removeAll()
        for imgStr in imageStringArray
        {
          self.imageArray.append(UIImage.init(named: imgStr) ?? UIImage.init())
        }

    }
    func configureTimer()
    {
        self.timer.invalidate()
        self.imgView.image = self.imageArray[self.photoCount] //Set Default Image First Time
        self.timer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true, block: { (timer) in
            if (self.photoCount < self.imageArray.count - 1){
                self.photoCount = self.photoCount + 1;
            }else{
                self.photoCount = 0;
            }
            if let imageView = self.imgView {
                UIView.transition(with: imageView, duration: 2.0, options: .transitionCrossDissolve, animations: {
                    imageView.image = self.imageArray[self.photoCount]
                }, completion: nil)
            }
        })
    }
}

1

在下载图像并在UITableView/UICollectionView单元格中显示时,您需要处理许多情况:

  1. 线程:图像应该在主线程上分配给UIImageView
  2. 下载完成后,请检查单元格是否仍然可见,并将其分配给正确的索引。

我强烈建议使用其中一个库来完成这项工作,例如SDWebImage


这里的问题不在于下载器,因为您可以在演示中查看,即使资产未正确加载,因此问题在于图像扩展名。 - Jaydeep Vyas

0

这里实际上发生的是collectionView正在重用之前的单元格,因此当图像正在下载时,先前单元格中的图像会加载到新单元格中,为了消除这种行为,您需要设置一个占位符图像或者您可以将图像设置为空。

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath)
        let image = cell.viewWithTag(1) as! UIImageView
         image.image = "placeholderImage" // replace it with your place holder image 
//Or 
//     image.image = UIImage()
        let imgArr =  imagesArray[indexPath.row]
        image.downloadImageAndAnimateIt(imageStringArray: imgArr)
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let size = self.collectionView.bounds.size.width / 2 - 5
        return CGSize(width: size, height: size - 5)
    }

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {


    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接