UICollectionVIew: оживить ячейки, когда они прокручиваются
Я хотел бы, чтобы элементы в моем UICollectionView
отображались для просмотра, когда пользователь прокручивает список (я использую подкласс UICollectionViewFlowLayout
).
Я указываю позицию в Менеджере макетов, то, что я хотел бы сделать, это также указать начальное преобразование и применить это в анимации в правильное время (когда ячейка сначала появится на экране). Чтобы увидеть эффект, который я имею в виду, проверьте приложение Google Plus на iOS. В идеале другое преобразование зависит от местоположения ячейки.
Кажется, я не могу найти способ узнать, когда отображается ячейка (эквивалент willDisplayCell
, как есть на UITableView
), или любые указатели на то, куда идти для этого.
Любые предложения?
Вы можете просто выделить анимацию в Google Plus на этом снимке экрана:
![Example in the Google Plus App]()
Кроме того, взгляните на iPhoto на iPad. Я не знаю, использует ли они UIcollectionView (возможно, нет, поскольку он работал на iOS5), но это тот вид, который я искал, кажется, что фотографии появляются справа.
Ответы
Ответ 1
Вы можете добиться этого эффекта независимо от пользовательского макета.
Код анимации должен находиться внутри 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
на наличие анимированных ячеек с разных позиций на более сложных макетах, а также оживить другие свойства вместе с фреймом или применить преобразование.
Ответ 2
Вам нужно переопределить initialLayoutAttributesForAppearingItemAtIndexPath:
в макете просмотра коллекции. Здесь вы можете установить любой атрибут в элементе атрибутов макета (включая преобразование), который будет анимирован к фактическим атрибутам после появления ячейки.
Если объект стандартных атрибутов макета не дает вам достаточно параметров, вы можете подклассифицировать его, добавить дополнительные атрибуты и переопределить applyLayoutAttributes:
в своей ячейке, чтобы получить дополнительные свойства.
Это будет работать, только когда вы добавляете ячейки в представление коллекции.
Чтобы преобразования, применяемые к ячейкам при прокрутке вниз по представлению коллекции, я бы посмотрел на их применение либо непосредственно в ячейку (в cellForItem
...), либо в атрибутах макета, возможно, это свойство называется initialTransform
. При применении атрибутов макета к ячейке вы должны проверить initialTransform
, применить ее, затем установить ее на идентификатор, а затем запустить анимацию, чтобы перейти к преобразованию идентичности, поэтому она будет применяться только тогда, когда ячейка была сначала прокручена на экран. Я не реализовал ничего подобного, это просто предположение о том, как я это сделаю.
Ответ 3
Как отметил Марк в комментарии, он закончил использование вида прокрутки, которое я хочу показать, как это сделать со стандартным представлением таблицы. Это не тот эффект, который наблюдается в 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) {
}];
}