在UICollectionView / UITableView中设置scrollView的偏移量会导致过早消失的单元格 [英] Animating the offset of the scrollView in a UICollectionView/UITableView causes prematurely disappearing cells

查看:563
本文介绍了在UICollectionView / UITableView中设置scrollView的偏移量会导致过早消失的单元格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个UICollectionView,其自定义布局非常类似于UITableView(它垂直滚动)。 UICollectionView仅同时显示3个单元格,其中一个是当前活动的单元格:

We have a UICollectionView with a custom layout very similar to UITableView (it scrolls vertically). The UICollectionView displays only 3 cells simultaneously, with one of them being the currently active cell:

[ 1 ]
[*2*]
[ 3 ]

(此处的活动单元格为#2。)细胞高约280个点,因此只有活动细胞在屏幕上完全可见。用户不直接滚动视图进行导航,而是水平滑动活动单元格以前进到下一个单元格。然后,我们做一些奇特的动画并滚动UICollectionView,以便下一个单元格处于活动位置,从而使其成为活动的单元格,将旧的单元格移开并调出队列中的下一个单元格:

(The active cell here is #2.) The cells are roughly 280 points high, so only the active cell is fully visible on the screen. The user doesn't directly scroll the view to navigate, instead, she swipes the active cell horizontally to advance to the next cell. We then do some fancy animations and scroll the UICollectionView so the next cell is in the "active" position, thus making it the active one, moving the old one away and bringing up the next cell in the queue:

[ 2 ]
[*3*]
[ 4 ]

这里的问题是设置UICollectionView的偏移量。我们目前在一个UIView动画块( self.collectionView.contentOffset = targetOffset; )中设置它以及其他三个动画属性,这些属性大部分效果很好,但会导致第一个单元格(即使在延迟间隔完成之前,一旦动画开始运行,先前激活的,在后一种情况下,#2)就会消失。这绝对不是理想的。

The problem here is setting the UICollectionView's offset. We currently set it in a UIView animation block (self.collectionView.contentOffset = targetOffset;) along with three other animating properties, which mostly works great, but causes the first cell (the previously active one, in the latter case, #2) to vanish as soon as the animation starts running, even before the delay interval completes. This is definitely not ideal.

我已经想到了一些解决方案,但无法弄清楚最好的解决方案:

I've thought of some solutions, but can't figure out the best one:


  1. 荒谬地放大UICollectionView的框架以适应五个单元格而不是三个单元格,从而迫使它将单元格保留在内存中,即使它们在屏幕外。我已经尝试了这个并且它有效,但它听起来像是一个非常脏的黑客。

  1. Absurdly enlarge the UICollectionView's frame to fit five cells instead of three, thus forcing it to keep the cells in memory even if they are offscreen. I've tried this and it works, but it sounds like an awfully dirty hack.

拍摄消失细胞的渲染内容的快照,把它放好在UIImageView中,将UIImageView添加为scrollView的子视图,就在单元格离开旧单元格的完全相同位置之前,一旦动画结束就将其删除。听起来比以前的选择(内存方面,至少),但仍然有点hacky。我也不知道实现这一目标的最佳方法,请指出正确的方向。

Take a snapshot of the rendered content of the vanishing cell, put it in a UIImageView, add the UIImageView as a subview of the scrollView just before the cell goes away in the exact same position of the old cell, removing it once the animation ends. Sounds less sucky than the previous option (memory-wise, at least), but still kinda hacky. I also don't know the best way to accomplish this, please point me in the right direction.


  1. Switch到UIScrollView的 setContentOffset:animated:。我们实际上已经习惯了这个,它修复了消失的单元格问题,但是与其他UIView动画并行运行显然会竞争主线程的注意力,从而在单核设备上创建一个非常不稳定的动画(iPhone 3GS / 4)。它也不允许我们改变动画的持续时间或缓和,因此感觉与其他动画不同步。如果我们能找到一种方法使其与UIView块动画协调工作,仍然是一个选项。

  1. Switch to UIScrollView's setContentOffset:animated:. We actually used to have this, and it fixed the disappearing cell issue, but running this in parallel with the other UIView animations apparently competes for the attention of the main thread, thus creating a terribly choppy animation on single-core devices (iPhone 3GS/4). It also doesn't allow us to change the duration or easing of the animation, so it feels out of sync with the rest. Still an option if we can find a way to make it work in harmony with the UIView block animations.

切换到UICollectionView的 scrollToItemAtIndexPath: atScrollPosition:动画:。没试过这个,但它有一个很大的缺点:目标滚动位置只需要3个可能的常量(至少适用于这种情况): UICollectionViewScrollPositionTop UICollectionViewScrollPositionCenteredVertically UICollectionViewScrollPositionBottom 。活动单元可以改变其高度,但它总是必须距离窗口顶部35个点,并且这些选项不能提供足够的控制来完成设计。它也可能与3.1一样有问题。仍然是一个选项,因为可能有一种方法可以解决我不知道的滚动位置问题,并且它可能与主线程没有相同的问题,这似乎不太可能。

Switch to UICollectionView's scrollToItemAtIndexPath:atScrollPosition:animated:. Haven't tried this, but it has a big downside: it only takes 3 possible constants (that apply to this case, at least) for the target scroll position: UICollectionViewScrollPositionTop, UICollectionViewScrollPositionCenteredVertically and UICollectionViewScrollPositionBottom. The active cell could vary its height, but it always has to be 35 points from the top of the window, and these options don't provide enough control to accomplish the design. It could also potentially be just as problematic as 3.1. Still an option because there might be a way to go around the scroll position thing that I don't know of, and it might not have the same issue with the main thread, which seems unlikely.


任何帮助将不胜感激。请询问您是否需要澄清。非常感谢!

Any help will be greatly appreciated. Please ask if you need clarification. Thanks a lot!

推荐答案

我选择#2。这是渲染和存储的代码片段:

I went with #2. Here's the snippet that does the rendering and storing:

UIGraphicsBeginImageContext(theCell.bounds.size);
[theCell.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *renderedCellImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

该方法的其余部分与我上面描述的非常相似,但有一点需要注意:这必须是在实际使用图像之前和在后台线程上完成,因为在iPhone上渲染可能需要1秒钟。希望这对某人有帮助。

The rest of the method was pretty much as I described above, with one caveat: this has to be done before the image is actually used and on a background thread, because rendering can take up to 1 full second on an iPhone 4. Hope this helps somebody.

这篇关于在UICollectionView / UITableView中设置scrollView的偏移量会导致过早消失的单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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