ios UICollectionVIew:在单元格滚动时为其设置动画
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17764991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UICollectionVIew: Animate cells as they scroll in
提问by Marc
I would like items in my UICollectionView
to animate in to view as the user scrolls through the list (I am using a subclass of UICollectionViewFlowLayout
).
UICollectionView
当用户滚动列表时,我希望我中的项目进行动画查看(我使用的是 的子类UICollectionViewFlowLayout
)。
I specify the position in the Layout Manager, what I would like to be able to do is to also specify an initial transform and have that applied in an animation at the correct time (when the cell first appears on screen). To see the effect I mean, check out the Google Plus app on iOS. Ideally a different transform depending on the location of the cell.
我在布局管理器中指定了位置,我希望能够做的是还指定一个初始转换,并在正确的时间(当单元格首次出现在屏幕上时)应用到动画中。要查看我的意思,请查看 iOS 上的 Google Plus 应用程序。理想情况下,不同的变换取决于单元格的位置。
I can't seem to find a way to find out when a cell is displayed (no equivalent of willDisplayCell
as there is on UITableView
) or any pointers on where to go for this.
我似乎无法找到一种方法来确定单元格何时显示(与willDisplayCell
on没有等价物UITableView
)或有关该去哪里的任何指示。
Any suggestions?
有什么建议?
You can just about make out the animation in Google Plus in this screen shot:
您可以在此屏幕截图中查看 Google Plus 中的动画:
Also, take a look at iPhoto on the iPad. I don't know if they're using a UIcollectionView (probably not, as it worked on iOS5) but this is the sort if effect I'm looking for, the photos appear to fly in from the right.
另外,看看 iPad 上的 iPhoto。我不知道他们是否在使用 UIcollectionView(可能不是,因为它在 iOS5 上工作)但这是我正在寻找的那种效果,照片似乎从右边飞进来。
回答by Cezar
You can achieve this effect independently of having a custom layout.
您可以独立于自定义布局来实现此效果。
The animation code should go inside collectionView:cellForItemAtIndexPath:
动画代码应该在里面 collectionView:cellForItemAtIndexPath:
When a cell is dequeued, its frame
will be set to what is specified in your layout. You can store it in a temporary variable as the final frame
for the cell. You can then set the cell.frame
to a initial position outside the screen, and then animate towards the desired final position. Something along the lines of:
当一个单元格出列时,frame
它将被设置为您的布局中指定的内容。您可以将它存储在一个临时变量中作为frame
单元格的最终变量。然后,您可以将 设置为cell.frame
屏幕外的初始位置,然后朝着所需的最终位置设置动画。类似的东西:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionView *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
CGRect finalCellFrame = cell.frame;
//check the scrolling direction to verify from which side of the screen the cell should come.
CGPoint translation = [collectionView.panGestureRecognizer translationInView:collectionView.superview];
if (translation.x > 0) {
cell.frame = CGRectMake(finalCellFrame.origin.x - 1000, - 500.0f, 0, 0);
} else {
cell.frame = CGRectMake(finalCellFrame.origin.x + 1000, - 500.0f, 0, 0);
}
[UIView animateWithDuration:0.5f animations:^(void){
cell.frame = finalCellFrame;
}];
return cell;
}
The code above will animate cells on a horizontal UICollectionView
, coming from the top of the screen, and from either side, depending on the scrolling direction. You could also check the current indexPath
to have cells animating from different positions on more complicated layouts, as well as animate other properties along with the frame, or apply a transform.
上面的代码将在水平方向上动画单元格UICollectionView
,来自屏幕顶部和两侧,具体取决于滚动方向。您还可以检查当前indexPath
让单元格在更复杂的布局上从不同位置动画,以及与框架一起动画其他属性,或应用变换。
回答by jrturton
You need to override initialLayoutAttributesForAppearingItemAtIndexPath:
in your collection view layout. Here you can set any attribute on the layout attributes item (including the transform) which will be animated to the actual attributes after the cell has appeared.
您需要initialLayoutAttributesForAppearingItemAtIndexPath:
在集合视图布局中进行覆盖。在这里,您可以在布局属性项(包括转换)上设置任何属性,这些属性将在单元格出现后动画为实际属性。
If the standard layout attributes object doesn't give you enough options, you can subclass it, add extra attributes, and override applyLayoutAttributes:
on your cell to pick up the extra properties.
如果标准布局属性对象没有为您提供足够的选项,您可以将其子类化,添加额外的属性,并覆盖applyLayoutAttributes:
您的单元格以获取额外的属性。
This will only work when you are adding cells to the collection view.
这仅在您将单元格添加到集合视图时才有效。
To have transforms applied to cells as you scroll down the collection view, I'd look at applying them either directly to the cell (at cellForItem
...) or in the layout attributes, perhaps a property called initialTransform
. When applying the layout attributes to the cell, you'd check the initialTransform
, apply it, then set it to identity, then trigger an animation to go to the identity transform, so it would only be applied when the cell was first scrolled onto the screen. I haven't implemented anything like this, it's just a guess as to how I would do it.
要在向下滚动集合视图时将转换应用于单元格,我会考虑将它们直接应用于单元格(at cellForItem
...)或布局属性,也许是一个名为initialTransform
. 将布局属性应用于单元格时,您需要检查initialTransform
,应用它,然后将其设置为身份,然后触发动画以进行身份转换,因此它只会在单元格第一次滚动到屏幕上时应用. 我还没有实现过这样的东西,这只是一个关于我将如何做的猜测。
回答by vikingosegundo
As Marc mentioned in a comment, that he ended up using a scroll view I want to show how to do it with a standard table view. It is not the same effect as seen in google+ but could be adapted easily.
正如 Marc 在评论中提到的,他最终使用了滚动视图,我想展示如何使用标准表格视图来实现。它与在 google+ 中看到的效果不同,但可以轻松调整。
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
static CGFloat duration = .5;
static NSUInteger xOffset = 50;
static NSUInteger yOffset = 200;
if(scrollDirection == STAScrollDirectionDown && lastAnimatedIndex < indexPath.row)
{
cell.frame = CGRectMake(cell.frame.origin.x - xOffset, cell.frame.origin.y+yOffset, cell.frame.size.width, cell.frame.size.height);
[UIView animateWithDuration:duration
animations:^{
cell.frame = CGRectMake(cell.frame.origin.x + xOffset, cell.frame.origin.y - yOffset, cell.frame.size.width, cell.frame.size.height);
} completion:^(BOOL finished) {
lastAnimatedIndex = indexPath.row;
}];
}
}
Just before the cell is being displayed we assign an offset (and possibly a rotation) to each cell and than we animate it back to the previous settings.
就在显示单元格之前,我们为每个单元格分配一个偏移量(可能还有一个旋转),然后我们将其动画化回之前的设置。
a little more exciting example:
一个更令人兴奋的例子:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
CATransform3D rotation = CATransform3DMakeRotation( (90.0*M_PI)/180, .0, 0.5, 0.5);
cell.contentView.alpha = 0.8;
cell.contentView.layer.transform = rotation;
cell.contentView.layer.anchorPoint = CGPointMake(0, 0.5);
[UIView animateWithDuration:.5
animations:^{
cell.contentView.layer.transform = CATransform3DIdentity;
cell.contentView.alpha = 1;
cell.contentView.layer.shadowOffset = CGSizeMake(0, 0);
} completion:^(BOOL finished) {
}];
}