UICollectionView动画单元格大小变化导致不良行为 [英] UICollectionView animating cell size change causes undesired behavior

查看:107
本文介绍了UICollectionView动画单元格大小变化导致不良行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个UICollectionViewController,它使用标准的 UICollectionViewFlowLayout 来显示单元格的单个垂直列.我尝试在轻按单元格时在单元格上创建展开/折叠动画.我使用以下代码来完成此任务:

I have a UICollectionViewController that using a standard UICollectionViewFlowLayout to display a single vertical column of cells. I am attempting to create an expand/collapse animation on a cell when a cell is tapped. I use the following code to accomplish this:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath (NSIndexPath *)indexPath
{
    [self.feedManager setCurrentlySelectedCellIndex:indexPath.item];
    [self.collectionView performBatchUpdates:nil completion:nil];
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    //Return the size of each cell to draw
    CGSize cellSize = (CGSize) { .width = 320, .height = [self.feedManager heightForCellAtIndexPath:indexPath] };
    return cellSize;
}

管理对象上的'selectedCellIndex'属性告诉数据模型在heightForCellAtIndexpath内返回扩展或折叠的大小:

The 'selectedCellIndex' property on my managing object tells the data model to return an expanded or collapsed size inside of heightForCellAtIndexpath:

[self.collectionView performBatchUpdates:nil completion:nil];

然后, performBatchUpdates:completiong:方法可以很好地将大小更改动画化.然而!发生动画时,展开的单元格可能会导致屏幕底部的部分可见的单元格离开屏幕.

Then the performBatchUpdates:completiong: method animates this size change nicely. However! When the animation happens, the expanding cell may cause a partially visible cell at the bottom of the screen to go off the screen.

如果是这种情况,然后我折叠了此单元格,则当前不在屏幕上的单元格将在没有动画的情况下捕捉到其旧位置,而所有其他可见单元格将根据需要进行动画处理.我的直觉说这是正确的行为,因为执行折叠动画时该单元不在屏幕上,并且不包括在动画渲染过程中.我的问题变成了,如何防止这种情况发生?

If this is the case and I subsequently collapse this cell, the now off screen cell will snap to its old position without animation, while all of the other visible cells will animate as desired. My intuition says that this is the correct behaviour since the cell is off screen when the collapse animation is being performed, and is not being included in the animation rendering process. My question becomes, how do I prevent this from happening?

无论它们是否不在屏幕上,我都希望所有这些单元一起进行动画处理.有什么想法吗?

I would prefer all of the cells to animate together regardless if they are off screen or not. Any thoughts?

推荐答案

这是一个 UICollectionViewFlowLayout 错误,但是有一种解决方法.问题是 initialLayoutAttributesForAppearingItemAtIndexPath:返回的属性具有错误的帧.具体而言,它们具有最终的屏幕上位置而不是初始屏幕外位置的帧.您只需要重写此方法并返回正确的帧即可.覆盖的基本结构如下所示:

This is a UICollectionViewFlowLayout bug, but there is a workaround. The problem is that the attributes returned by initialLayoutAttributesForAppearingItemAtIndexPath: have the wrong frames. Specifically, they have the frames of the final, on screen position rather than the initial, off screen position. You just need to override this method and return correct frames. The basic structure of the override would look something like this:

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
    UICollectionViewLayoutAttributes *pose = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath];
    if (<test for incorrect frame>) {
        CGRect frame = pose.frame;
        frame.origin.y = <calculate correct frame>;
        pose.frame = frame;
    }
    return pose;
}

您将负责确定需要调整框架的场景,这可能涉及保持自己的内部状态.我没有通过这种逻辑进行工作,但是我做了一次粗略的测试,并且能够获得流畅的动画.

You will be responsible for identifying scenarios where the frames need to be adjusted, which may involve keeping your own internal state. I haven't worked through this logic, but I did do a crude test and was able to get smooth animation.

概括地说,根据我的经验, UICollectionViewFlowLayout 如此容易出问题,并且如果要在屏幕上和屏幕外移动的项目与任何插入物组合在一起,那么有很多极端的情况要解决,删除或移动,发现我更容易滚动自己的简单布局.如果您不打算进行任何插入,删除或移动,那么覆盖 UICollectionViewFlowLayout 可能是最好的选择.

Generalizing a bit, it is my experience that there UICollectionViewFlowLayout is so buggy and there are so many corner cases to contend with if you've got items moving on and off screen combined with any inserts, deletions, or moves, that I've found it easier to roll my own simple layouts. If you're not going to do any inserts, deletions, or moves, then overriding UICollectionViewFlowLayout may well be your best bet.

让我知道是否需要更多帮助.

Let me know if you need more help.

编辑

如果您对查看第三方布局感兴趣,我将开放我的自定义网格布局扩展项目.还有一个排序&使用动画排序和过滤功能过滤项目.通过这两个项目,您都可以在流布局和网格布局之间切换,以便看到改进.

If you're interested in looking at a 3-rd party layout, I open sourced my custom grid layout VCollectionViewGridLayout and added an example project demonstrating smooth expanding cell height. Try running the Expand project. There is also a Sort & Filter project with animated sorting and filtering. Both projects let you toggle between flow layout and grid layout so you can see the improvement.

这篇关于UICollectionView动画单元格大小变化导致不良行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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