【问题标题】:UIImageView animated doesn't work properly inside UICollectionViewCellUIImageView 动画在 UICollectionViewCell 内无法正常工作
【发布时间】:2015-09-02 14:47:40
【问题描述】:

我想在UICollectionViewCell 中添加一个UIImageView 动画,所以我想出了这个代码:

    import UIKit

class MainViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

    var items:[String] = ["one", "two", "three", "four"]

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor(red: 220/255, green: 220/255, blue: 220/255, alpha: 1.0)
        self.view.addSubview(self.collectionView)
    }

    lazy var collectionView:UICollectionView = {
        var cv = UICollectionView(frame: self.view.bounds, collectionViewLayout: self.flowLayout)
        cv.delegate = self
        cv.dataSource = self
        cv.bounces = true
        cv.alwaysBounceVertical = true
        cv.autoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth
        cv.registerClass(CustomCell.self, forCellWithReuseIdentifier: "cell")
        cv.backgroundColor = UIColor(red: 220/255, green: 220/255, blue: 220/255, alpha: 1.0)
        return cv
    }()

    lazy var flowLayout:UICollectionViewFlowLayout = {
        var flow = UICollectionViewFlowLayout()
        flow.sectionInset = UIEdgeInsetsMake(2.0, 2.0, 2.0, 2.0)
        return flow
    }()


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize{

        let width:CGFloat = self.view.bounds.size.width*0.98;
        let height:CGFloat = 150.0;
        return CGSizeMake(width, height)
    }

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

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CustomCell
        cell.layer.cornerRadius = 4
        cell.backgroundColor = UIColor.whiteColor()
        cell.imgView.animationImages = ["1","2","3","4","5", "6","7","8"].map{UIImage(named: $0)!}
        cell.imgView.animationDuration = NSTimeInterval(0.8)
        cell.imgView.startAnimating()
        return cell
    }

    func collectionView(collectionView: UICollectionView, shouldHighlightItemAtIndexPath indexPath: NSIndexPath) -> Bool {
         return true
    }

    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
        var alert = UIAlertController(title: "Alert!", message: "Cell tapped", preferredStyle: UIAlertControllerStyle.Alert)
        var action = UIAlertAction(title: "ok", style: UIAlertActionStyle.Cancel) { (dd) -> Void in }
        alert.addAction(action)
        self.presentViewController(alert, animated: true, completion: nil)
    }

}

这是我的 MainViewController,以编程方式添加了 CollectionView

    import UIKit

class CustomCell: UICollectionViewCell {

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(self.imgView)
    }

    lazy var imgView:UIImageView = {
        var iv = UIImageView()
        iv.contentMode = UIViewContentMode.ScaleAspectFill
        return iv
    }()

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.imgView.frame = CGRectMake(6,15,self.frame.width*0.2, self.frame.height*0.8)
    }
}

这是我的自定义 UICollectionViewCellUIImageView

我的问题是当你点击一个单元格时,UIImageView 消失了。为了解决这个问题,我开始寻找另一个 UICoolectionView delegate 方法。然后我尝试使用shouldHighlightItemAtIndexPath,但如果我使用此方法返回false,动画效果很好,但集合视图停止响应didSelectItemAtIndexPath

这是一个 github 存储库,其中包含显示问题的代码:https://github.com/gazolla/ImageAnimation已更新解决方案

解决方案:

在 matt 的帮助下,我对代码进行了以下更改:

1) 将图像数组添加到highlightedAnimationImages 属性

let animationArray = ["1","2","3","4","5", "6","7","8"].map{UIImage(named: $0)!}
cell.imgView.highlightedAnimationImages = animationArray

2) 取消选中单元格时重新启动动画

 func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? CustomCell{
        cell.imgView.startAnimating()
    }
 }

3) 选择单元格时重新启动动画

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! CustomCell
    cell.imgView.startAnimating()

    //...

}

解决方案 2:

经过一些测试,我发现当你长按一个单元格UIImageView又消失了,所以我们必须在另外两种方法中重新启动动画:

1) didHighlightItemAtIndexPath

func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath) {
        if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? CustomCell{
            cell.imgView.startAnimating()
        }

  }

2) didUnhighlightItemAtIndexPath

func collectionView(collectionView: UICollectionView, didUnhighlightItemAtIndexPath indexPath: NSIndexPath) {
    if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? CustomCell{
        cell.imgView.startAnimating()
    }
}

【问题讨论】:

  • 我不得不使用解决方案 2。
  • 解决方案 1 有效。

标签: ios swift animation uiimageview uicollectionviewcell


【解决方案1】:

当您选择单元格时,图像视图会查看它的highlightedAnimationImages,而不是它的animationImages。你没有设置highlightedAnimationImages,所以你什么也看不到。

这是一个截屏视频,显示此方法可行。当背景为灰色时(即其selectedBackgroundView),单元格被选中,但动画仍在继续:

【讨论】:

  • 感谢您的回答,马特。我将highlightedAnimationImages 添加到cellForItemAtIndexPath 中,但它不起作用。我应该把这个命令放在另一个地方吗?
  • 我在问题中添加了一个带有我的代码的 github 存储库。
  • 你还得重新开始动画。
  • Matt,我发现了另一个问题,当您点击并按住一个单元格时,有时动画会消失。可能我将不得不在另一点重新启动动画。你知道我们是否可以检测到点击并按住 uicollectionviewcell 吗?
  • 您是否考虑过使用动画 image 代替动画图像 view?他们永远不会停止。
【解决方案2】:

如果其他人遇到这个讨厌的错误并且上述解决方案没有帮助 - 请尝试在您的单元格的 prepareForReuse() 函数中调用 imageView.stopAnimating()

【讨论】:

    【解决方案3】:

    来自@Sebastian 的解决方案 2 的 Swift 4 版本。

    func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
        if let cell = collectionView.cellForItem(at: indexPath) as? CustomCell {
            cell.imgView.startAnimating()
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
        if let cell = collectionView.cellForItem(at: indexPath) as? CustomCell {
            cell.imgView.startAnimating()
        }
    }
    

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,但我没有让“didDeselectItemAtIndexPath”工作,所以我解决问题的方法是在图片上添加一个没有功能的按钮。

      所以当你触摸图片时,你会改为触摸按钮。

      【讨论】:

        【解决方案5】:

        The solution 1 and 2 based on Sebastian 给了我灵感。当 UITableViewCell isSelectedisHighlighted 状态发生变化时,会调用setSelected:animated:setHighlighted:animated 方法。所以,我重写了自定义 UITableViewCell 的方法。

        class DCFWFailReasonCell: UITableViewCell {
        
            // Local flag for UIImageView animation.
            fileprivate var isAnimation: Bool = false
        
            // Setup animation images 
            func configure(animateImage: [UIImage], duration: TimeInterval) {
                imgView.animationImages = animateImage
                imgView.highlightedAnimationImages = animateImage
                
                imgView.animationDuration = duration
                imgView.animationRepeatCount = 0 //< 0 infinite
                
                imgView.startAnimating()
        
                // imgView has animation.         
                isAnimation = true
            }
        
            override func setSelected(_ selected: Bool, animated: Bool) {
                super.setSelected(selected, animated: animated)
                
                // 
                if (self.isAnimation) {
                    imgView.startAnimating()
                }
            }
            
            override func setHighlighted(_ highlighted: Bool, animated: Bool) {
                super.setHighlighted(highlighted, animated: animated)
                
                if (self.isAnimation) {
                    imgView.startAnimating()
                }
            }
        
        }
        

        【讨论】:

          【解决方案6】:

          这是我的解决方案,效果很好

          class MyImageView: UIImageView {
              
              override func stopAnimating() {
                  super.stopAnimating()
                  startAnimating()
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2012-10-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-29
            • 2021-06-11
            相关资源
            最近更新 更多