UICollectionViewCell - contents do not animate alongside cell's contentView

前端 未结 3 570
予麋鹿
予麋鹿 2021-01-31 20:32

Problem looks like this: http://i.imgur.com/5iaAiGQ.mp4 (red is a color of cell.contentView)

Here is the code: https://github.com/nezhyborets/UICollectionViewContentsAni

相关标签:
3条回答
  • 2021-01-31 21:06

    The solution is very easy. First, in ViewController.collectionView(_,didSelectItemAt:), write only this:

    collectionView.performBatchUpdates({
            self.selectedIndex = indexPath.row
        }, completion: nil)
    

    And then, in the class ProblematicCollectionViewCell add this func:

    override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
        super.apply(layoutAttributes)
    
        self.layoutIfNeeded()
    }
    

    Enjoy!

    0 讨论(0)
  • 2021-01-31 21:11

    This is a finicky problem, and you're very close to the solution. The issue is that the approach to animating layout changes varies depending on whether you're using auto layout or resizing masks or another approach, and you're currently using a mix in your ProblematicCollectionViewCell class. (The other available approaches would be better addressed in answer to a separate question, but note that Apple generally seems to avoid using auto layout for cells in their own apps.)

    Here's what you need to do to animate your particular cells:

    1. When cells are selected or deselected, tell the collection view layout object that cell sizes have changed, and to animate those changes to the extent it can do so. The simplest way to do that is using performBatchUpdates, which will cause new sizes to be fetched from sizeForItemAt, and will then apply the new layout attributes to the relevant cells within its own animation block:

      func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
          self.selectedIndex = indexPath.row
          collectionView.performBatchUpdates(nil)
      }
      
    2. Tell your cells to layout their subviews every time the collection view layout object changes their layout attributes (which will occur within the performBatchUpdates animation block):

      // ProblematicCollectionViewCell.swift
      
      override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
          super.apply(layoutAttributes)
          layoutIfNeeded()
      }
      

    If you want greater control over your animations, you can nest the call to performBatchUpdates inside a call to one of the UIView.animate block-based animation methods. The default animation duration for collection view cells in iOS 10 is 0.25.

    0 讨论(0)
  • 2021-01-31 21:14

    You can apply a transform to a cell, although it has some drawbacks, such as handling orientation changes.

    For extra impact, I have added a color change and a spring effect in the mix, neither of which could be achieved using the reloading route:

        func collectionView(_ collectionView: UICollectionView,
                            didSelectItemAt indexPath: IndexPath) {
            UIView.animate(
                withDuration: 0.4,
                delay: 0,
                usingSpringWithDamping: 0.4,
                initialSpringVelocity: 0,
                options: UIViewAnimationOptions.beginFromCurrentState,
                animations: {
                    if( self.selectedIndexPath.row != NSNotFound) {
                        if let c0 =
                            collectionView.cellForItem(at: self.selectedIndexPath)
                        {
                            c0.contentView.layer.transform = CATransform3DIdentity
                            c0.contentView.backgroundColor = UIColor.lightGray
                        }
                    }
                    self.selectedIndexPath = indexPath
                    if let c1 = collectionView.cellForItem(at: indexPath)
                    {
                        c1.contentView.layer.transform =
                            CATransform3DMakeScale(1.25, 1.25, 1)
                        c1.contentView.backgroundColor = UIColor.red
                    }
    
                },
                completion: nil)
        }
    
    0 讨论(0)
提交回复
热议问题