我希望UICollectionView
中的项目可以动画显示,因为用户滚动列表(我正在使用UICollectionViewFlowLayout
的子类)。
我在布局管理器中指定位置,我希望能够做的是指定一个初始变换,并在正确的时间(当单元格首次出现在屏幕上时)应用于动画中。要查看我的意思,请查看iOS上的Google Plus应用。理想情况下,不同的变换取决于细胞的位置。
我似乎无法找到一种方法来查明何时显示一个单元格(不等同于willDisplayCell
上的UITableView
)或任何有关此位置的指针。< / p>
有什么建议吗?
您可以在此屏幕截图中了解Google Plus中的动画:
另外,请看一下iPad上的iPhoto。我不知道他们是否正在使用UIcollectionView(可能不是,因为它在iOS5上工作),但这是我正在寻找的效果,照片似乎是从右边飞来的。
答案 0 :(得分:36)
您可以独立于自定义布局来实现此效果。
动画代码应该放在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
以使单元格在更复杂的布局上从不同位置设置动画,以及为框架设置其他属性的动画,或应用变换。
答案 1 :(得分:5)
您需要在集合视图布局中覆盖initialLayoutAttributesForAppearingItemAtIndexPath:
。在这里,您可以在布局属性项(包括转换)上设置任何属性,该属性将在单元格出现后设置为实际属性。
如果标准布局属性对象没有提供足够的选项,您可以对其进行子类化,添加额外的属性,并覆盖单元格上的applyLayoutAttributes:
以获取额外的属性。
这仅在将单元格添加到集合视图时才有效。
要在向下滚动集合视图时将变换应用于单元格,我会将它们直接应用于单元格(cellForItem
...)或布局属性,也许是一个名为initialTransform
。将布局属性应用于单元格时,您需要检查initialTransform
,应用它,然后将其设置为标识,然后触发动画转到标识转换,因此只有在单元格为首先滚动到屏幕上。我没有实现这样的任何东西,它只是猜测我将如何做到这一点。
答案 2 :(得分:3)
正如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;
}];
}
}
在显示单元格之前,我们为每个单元格指定一个偏移量(可能还有一个旋转),然后我们将其设置为以前设置的动画。
一个更令人兴奋的例子:
-(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) {
}];
}