在“收藏夹”视图单元格中使图像具有淡入淡出效果

时间:2019-07-10 05:55:08

标签: ios swift image animation uicollectionview

注意:我已经尝试了堆栈溢出中所有匹配的问题,但是没有一个问题可以解决,因此无法发布。

我有一个集合视图,其中有多个单元格,每个单元格都有一个图像视图。每个单元将具有不同的图像阵列,我需要通过淡入淡出的效果一个接一个地显示图像。第一次它正确显示,但是当我滚动时出现了问题。第一个单元格的图像显示在其他任何单元格中。图片会随机播放。


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)
                }
            })

        }

    }

}

图片不应该随机播放,并且应该与滚动之前保持在同一单元格中。

3 个答案:

答案 0 :(得分:1)

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

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

我强烈建议为此使用一个库,例如 SDWebImage

答案 1 :(得分: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) {


    }

答案 2 :(得分:0)

您必须创建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)
            }
        })
    }
}