UICollectionVIew:在滚动时为单元格添加动画
我希望在用户滚动列表时使用UICollectionView
项目进行动画显示(我使用的是UICollectionViewFlowLayout
的子类)。
我在布局管理器中指定位置,我希望能够做的是也指定一个初始变换,并在正确的时间(当单元格第一次出现在屏幕上时)在动画中应用。 要查看我的意思,请查看iOS上的Google Plus应用。 理想情况下,根据细胞的位置不同的变换。
我似乎无法找到一种方法来查明何时显示一个单元格(没有与UITableView
上的willDisplayCell
等效)或任何指向该目标的指针。
有什么建议么?
您可以在此屏幕截图中制作Google Plus中的动画:
另外,请看一下iPad上的iPhoto。 我不知道他们是否使用UIcollectionView(可能不是,因为它在iOS5上工作),但这是如果我正在寻找的效果,照片似乎从右侧飞入。
您可以独立于自定义布局来实现此效果。
动画代码应该放在collectionView:cellForItemAtIndexPath:
当一个单元格出队时,其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;
}
上面的代码将根据滚动方向为水平UICollectionView
上的单元格生成动画,这些单元格来自屏幕的顶部,以及来自任何一侧。 您还可以检查当前的indexPath
,让单元格从更复杂的布局上的不同位置进行动画制作,以及将其他属性与框架一起动画或应用变形。
您需要在集合视图布局中重写initialLayoutAttributesForAppearingItemAtIndexPath:
在这里,您可以设置布局属性项目(包括变换)上的任何属性,该属性将在单元格出现后被动画为实际属性。
如果标准布局属性对象没有给您足够的选项,您可以对它进行子类化,添加额外的属性,并覆盖您的单元格上的applyLayoutAttributes:
拾取额外的属性。
这只在将单元格添加到集合视图时才起作用。
要在向下滚动集合视图时将变换应用于单元格,我会考虑将它们直接应用于单元格(在cellForItem
)或布局属性(可能是名为initialTransform
的属性)。 将布局属性应用于单元格时,您需要检查initialTransform
,应用它,然后将其设置为标识,然后触发动画以进行标识转换,因此仅当单元格第一次滚动到屏幕。 我没有执行过这样的事情,只是猜测我该怎么做。
正如马克在评论中提到的那样,他最终使用了滚动视图,我想展示如何使用标准表视图进行操作。 它与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;
}];
}
}
就在显示单元格之前,我们为每个单元格分配一个偏移量(可能还有一个旋转),然后再将其设置回原来的设置。
一个更激动人心的例子:
-(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) {
}];
}
链接地址: http://www.djcxy.com/p/84161.html
上一篇: UICollectionVIew: Animate cells as they scroll in
下一篇: Advanced UICollectionView animation using invalidateLayout calls