UICollectionViewCell - 内容不会与单元格的 contentView 一起动画 [英] UICollectionViewCell - contents do not animate alongside cell's contentView

查看:23
本文介绍了UICollectionViewCell - 内容不会与单元格的 contentView 一起动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

当前状态:UICollectionViewCell 的 contentView 的内容不会随着 contentView 帧的变化而动画.它立即获得大小而无需动画.

Current status: The content of UICollectionViewCell's contentView does not animate alongside contentView frame change. It gets the size immediately without animation.

执行任务时遇到的其他问题:在我在 UICollectionViewCell 子类中执行此操作之前,contentView 也没有与单元格的框架更改一起动画:

Other issues faced when doing the task: The contentView was not animating alongside cell's frame change either, until i did this in UICollectionViewCell subclass:

override func awakeFromNib() {
    super.awakeFromNib()

    //Because contentView won't animate along with cell
    contentView.frame = bounds
    contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}

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

Other notes: Here is the code involved in cell size animation

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
}

我在使用collectionView.setCollectionViewLayout(newLayout, animated: true)时得到相同的结果,而使用collectionView.collectionViewLayout.invalidateLayout()时根本没有动画 而不是批处理更新中的 reloadData().

I get the same results when using collectionView.setCollectionViewLayout(newLayout, animated: true), and there is no animation at all when using collectionView.collectionViewLayout.invalidateLayout() instead of reloadData() inside batchUpdates.

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

UPDATE When I print imageView.constraints inside UICollectionView's willDisplayCell method, it prints empty array.

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: []
}

推荐答案

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

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.最简单的方法是使用 performBatchUpdates,这将导致从 sizeForItemAt 获取新的尺寸,然后将新的布局属性应用到它自己的相关单元格动画块:

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

  • 每次集合视图布局对象更改其布局属性(将在 performBatchUpdates 动画块中发生)时,告诉您的单元格布局其子视图:

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

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

    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.

    这篇关于UICollectionViewCell - 内容不会与单元格的 contentView 一起动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆