UICollectionViewCell - 内容不与单元格的contentView一起制作动画

Ole*_*ets 15 animation ios uicollectionview uicollectionviewcell

问题看起来像这样:http: //i.imgur.com/5iaAiGQ.mp4(红色是cell.contentView的颜色)

这是代码:https://github.com/nezhyborets/UICollectionViewContentsAnimationProblem

当前状态: UICollectionViewCell的contentView的内容不会与contentView框架更改一起动画.它立即获得大小没有动画.

执行任务时遇到的其他问题: contentView也没有动画到单元格的帧更改,直到我在UICollectionViewCell子类中执行此操作:

override func awakeFromNib() {
    super.awakeFromNib()

    //Because contentView won't animate along with cell
    contentView.frame = bounds
    contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
Run Code Online (Sandbox Code Playgroud)

其他说明: 以下是单元格大小动画中涉及的代码

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    self.selectedIndex = indexPath.row

    collectionView.performBatchUpdates({
        collectionView.reloadData() 
    }, completion: nil)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let isSelected = self.selectedIndex == indexPath.row
    let someSize : CGFloat = 90 //doesn't matter
    let sizeK : CGFloat = isSelected ? 0.9 : 0.65
    let size = CGSize(width: someSize * sizeK, height: someSize * sizeK)

    return size
}
Run Code Online (Sandbox Code Playgroud)

我使用时得到相同的结果collectionView.setCollectionViewLayout(newLayout, animated: true),并使用时,有没有动画都collectionView.collectionViewLayout.invalidateLayout()代替reloadData() inside batchUpdates.

更新 当我imageView.constraints在UICollectionView的willDisplayCell方法中打印时,它会打印出空数组.

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    for view in cell.contentView.subviews {
        print(view.constraints)
    }

    //Outputs
    //View: <UIImageView: 0x7fe26460e810; frame = (0 0; 50 50); autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x608000037280>>
    //View constraints: []
}
Run Code Online (Sandbox Code Playgroud)

jam*_*esk 23

这是一个棘手的问题,你非常接近解决方案.问题是,布局更改动画的方法取决于您是使用自动布局还是调整大小掩码或其他方法,并且您当前正在使用ProblematicCollectionViewCell类中的混合.(其他可用的方法可以更好地解决一个单独的问题,但请注意,Apple通常似乎避免在自己的应用程序中使用单元格的自动布局.)

以下是为特定单元格设置动画所需的操作:

  1. 选择或取消选择单元格时,请告知集合视图布局对象单元格大小已更改,并将这些更改设置为可以执行此操作的范围.最简单的方法是使用performBatchUpdates,这将导致从中获取新的大小sizeForItemAt,然后将新的布局属性应用于其自己的动画块中的相关单元格:

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        self.selectedIndex = indexPath.row
        collectionView.performBatchUpdates(nil)
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 每次集合视图布局对象更改其布局属性(将在performBatchUpdates动画块中发生)时,告诉您的单元格布置其子视图:

    // ProblematicCollectionViewCell.swift
    
    override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
        super.apply(layoutAttributes)
        layoutIfNeeded()
    }
    
    Run Code Online (Sandbox Code Playgroud)

如果您想要更好地控制动画,可以将调用嵌套performBatchUpdates到一个UIView.animate基于块的动画方法之一的调用中.iOS 10中集合视图单元格的默认动画持续时间为0.25.


Gab*_*iel 5

解决方案非常简单.首先,在ViewController.collectionView(_,didSelectItemAt :)中,只写下:

collectionView.performBatchUpdates({
        self.selectedIndex = indexPath.row
    }, completion: nil)
Run Code Online (Sandbox Code Playgroud)

然后,在classesmaticCollectionViewCell类中添加以下函数:

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

    self.layoutIfNeeded()
}
Run Code Online (Sandbox Code Playgroud)

请享用!