Ios UICollectionVIew:设置单元格滚动时的动画
我希望在用户滚动列表时,将我的Ios UICollectionVIew:设置单元格滚动时的动画,ios,objective-c,uikit,core-animation,uicollectionview,Ios,Objective C,Uikit,Core Animation,Uicollectionview,我希望在用户滚动列表时,将我的UICollectionView中的项目设置为动画以查看(我使用的是UICollectionViewFlowLayout的子类) 我在布局管理器中指定位置,我希望能够同时指定初始变换,并在正确的时间(当单元格首次出现在屏幕上时)将其应用于动画中。要了解其效果,请查看iOS上的Google Plus应用程序。理想情况下,根据单元的位置进行不同的变换 我似乎找不到一种方法来确定何时显示单元格(没有类似于UITableView上显示的willDisplayCell),也找
UICollectionView
中的项目设置为动画以查看(我使用的是UICollectionViewFlowLayout
的子类)
我在布局管理器中指定位置,我希望能够同时指定初始变换,并在正确的时间(当单元格首次出现在屏幕上时)将其应用于动画中。要了解其效果,请查看iOS上的Google Plus应用程序。理想情况下,根据单元的位置进行不同的变换
我似乎找不到一种方法来确定何时显示单元格(没有类似于UITableView
上显示的willDisplayCell
),也找不到指向该单元格的任何指针
有什么建议吗
在这个屏幕截图中,您可以在Google Plus中制作动画:
另外,看看iPad上的iPhoto。我不知道他们是否在使用UIcollectionView(可能不是,因为它在iOS5上工作),但这就是我要寻找的排序效果,照片似乎从右侧飞入。您需要在集合视图布局中覆盖出现的GitMetandexPath:的
初始布局属性。在这里,可以在布局属性项(包括变换)上设置任何属性,该属性将在单元出现后设置为实际属性的动画
如果标准布局属性对象没有提供足够的选项,则可以对其进行子类化,添加额外属性,并覆盖单元格上的applyLayoutAttributes:
,以获取额外属性
这仅在将单元格添加到集合视图时有效
要在向下滚动集合视图时将变换应用于单元格,我将考虑直接将变换应用于单元格(在cellForItem
..)或布局属性中,可能是一个名为initialTransform
的属性。将布局属性应用于单元格时,您需要检查初始转换,应用它,然后将其设置为identity,然后触发动画以转到identity转换,因此仅当单元格第一次滚动到屏幕上时才会应用它。我还没有实现任何类似的功能,只是猜测我将如何实现 您可以独立于自定义布局来实现此效果
动画代码应该放在collectionView:cellForItemAtIndexPath:
当一个单元格退出队列时,它的框架将设置为布局中指定的内容。您可以将其存储在临时变量中,作为单元格的最终帧。然后可以将单元格.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;
}
上面的代码将根据滚动方向,在水平UICollectionView
上对来自屏幕顶部和任意一侧的单元格设置动画。您还可以检查当前的索引XPath
,使单元格在更复杂的布局上从不同位置设置动画,以及随帧设置其他属性的动画,或者应用变换。正如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;
}];
}
}
如果我在这里设置断点,它只在屏幕旋转时被调用。标题注释似乎也表明了这一点。是否还有其他需要配置的内容?我正在对UICollectionViewFlowLayout进行子类化。在向视图中添加项目或滚动时应调用该方法。根据文档,在数据更改或需要重新绘制集合视图时调用该方法,而不是在滚动时调用,除非我做错了什么?您能否确认在滚动时触发了此回调?Quote“当集合视图中的数据发生更改并且要插入或删除项目时,集合视图会要求其布局对象更新布局信息。”从您的话中可以看出,我非常抱歉。我的答案中的方法只有在将单元格添加到集合视图时才有用,我关于滚动的评论是错误的。作为第一步,我将考虑在cellForItemAtIndexPath中应用转换,您可能必须将其作为单元格上的属性,并在applyLayoutAttributes中应用它(在super完成其工作后)。谢谢-我想我会发疯的:o)嘿,您最终得到了答案吗?我正在尝试实现相同的行为,将感谢您的帮助。不,抱歉-我最终使用了标准的滚动视图。@JackKapow,我在下面发布了一个可能有用的答案。@JackKapow我可能在一段时间内没有机会测试这个,所以如果您尝试一下,它会起作用,在这里让我知道,我会把它标记为已接受的答案。好的,我检查过了!非常好用,谢谢!嘿谢谢我玩了一会儿,现在它看起来很棒!我会让你知道如果我发现任何问题,谢谢!!!!你有没有办法让它只动画一次?我的意思是,当我第一次向下滚动时,我想让它动画化——然后我只想让新的细胞动画化(就像谷歌+),我知道你的意思。在Google+中,当新内容插入CollectionView数据源时,可能发生的事情是他们正在制作动画。为了防止在滚动时再次设置动画,我想您需要存储一个标志数组,并为每个已设置动画的indexPath设置它们的值。当为给定的indexPath对一个单元格进行出列时,你会检查该数组,看看是否应该设置动画。是的,我做了一些你说的事情,效果很好!实际上,当新数据到达数据源时,不需要设置动画,因为我使用的是单元格的消隐-单元格实际上是在滚动时加载的,所以我只跟踪已经加载的单元格。再次感谢@塞萨尔超级酒店
-(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) {
}];
}