I have a Horizontal UICollectionView with n number of records. Each cell has an UIImageView which needs to animate the Fadein Fadeout with some TimerInterval. So, i have planned to implement that reload my UICollectionView using NSTimer My code snippet,
....
....
if (collectionTimer) {
[collectionTimer invalidate];
collectionTimer = nil;
}
collectionTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(reloadCollection) userInfo:nil repeats:YES];
....
....
reloadCollection Method
-(void)reloadCollection{
[_collectionView reloadData];
}
cellForItemAtIndexPath Method
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
....
....
/* Basic Animation working fine*/
[UIView animateKeyframesWithDuration:1.0 delay:1.0 options:UIViewKeyframeAnimationOptionAutoreverse animations:^{
cell.articleImage.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.jpg", [images objectAtIndex:i]]];
} completion:nil];
/* Not working */
/* [UIView transitionWithView:cell.articleImage duration:1.0f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
cell.articleImage.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.jpg", [images objectAtIndex:i]]];
} completion:nil]; */
....
....
}
The basic animation works fine. But, whenever i am trying to implement UIViewAnimationOptionTransitionCrossDissolve with transitionWithView method. It will showing the animation, but immediately one more image loaded because of reloadData calling. How to fix this? How to animate only the images in UICollectionView
Any Idea appreciated!
My animation work like this:
cell.articleImage.alpha = 0.0;
[UIView animateWithDuration:0.3f animations:^{
[cell.articleImage setAlpha:1.0];
}];
Try to add the animation for visible cells without reloading the collectionView:
NSArray* visibleCells = [collectionView visibleCells];
[visibleCells enumerateObjectsUsingBlock:^(UICollectionViewCell* cell, NSUInteger idx, BOOL *stop) {
//TODO: add animation;
}];
Update
To animate new cells, you should start animation after adding cell to window. In cell you can override method didMoveToWindow:
- (void)didMoveToWindow
{
[super didMoveToWindow];
if (self.window && self.shouldStartAnimation)
{
[self startAnimation];
}
}
And in ViewController these methods:
- (void)animateVisibleCells
{
NSArray* visibleCells = [self.collectionView visibleCells];
[visibleCells enumerateObjectsUsingBlock:^(BTCollectionViewCell* cell, NSUInteger idx, BOOL *stop) {
[cell startAnimation];
}];
}
#define ANIMATION_DURATION (0.3)
- (void)animateCells
{
self.shouldAnimationStart = YES;
[self animateVisibleCells];
[NSTimer scheduledTimerWithTimeInterval:ANIMATION_DURATION target:self selector:#selector(endAnimateCells) userInfo:nil repeats:NO];
}
- (void)endAnimateCells
{
self.shouldAnimationStart = NO;
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
((BTCollectionViewCell*)cell).shouldStartAnimation = self.shouldAnimationStart;
}
But problem with synchronization of the animation continues to be (new animations will starts from 0 time). If you know method to start animation from concrete time, you can use it method in willDisplayCell
Well i guess that in your method cellForItemAtIndexPath you are not configuring animation right.
please use this.
[UIView animateKeyframesWithDuration:1.0 delay:0.1 options:UIViewKeyframeAnimationOptionAutoreverse animations:^{
cell.articleImage.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.jpg", [images objectAtIndex:i]]];
} completion:nil];
You were not assigning the delay properly to let animation work.
Hope it works for you now. Thanks
Related
Im trying to create a cool animation with my collection view selection. Basically I have a collection view of photo cells displayed. What I want to happen is have the cell pop out of its location, scale and move to the center of the screen where the user will be prompted to confirm the selection.
Here is my code so far, but currently the animation takes the cells original frame location, so if I scroll it doesnt take into account that the frame position is no longer the same.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
PhotoCell *cell = (PhotoCell *)[collectionView cellForItemAtIndexPath:indexPath];
collectionView.allowsSelection = NO;
[self createAnimationWithCell:cell];
}
- (void)createAnimationWithCell:(PhotoCell *)cell {
UIImageView *selectedImage = [[UIImageView alloc] initWithFrame:cell.bounds];
selectedImage.center = cell.center;
selectedImage.image = cell.imageView.image;
[self.view addSubview:selectedImage];
[UIView animateWithDuration:2.5 animations:^{
selectedImage.center = self.view.center;
} completion:^(BOOL finished) {
[selectedImage removeFromSuperview];
self.collectionView.allowsSelection = YES;
}];
}
I solved it myself:
For those who are experiencing the same problem, we have to take into account how much the collection view has scrolled (offset) and use that information. I created a variable called collectionViewOffset and gave it an initial value of 0.0
then used:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// getting the scroll offset
collectionViewOffset = scrollView.contentOffset.y;
NSLog(#"offset: %f", collectionViewOffset);
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
PhotoCell *cell = (PhotoCell *)[collectionView cellForItemAtIndexPath:indexPath];
//collectionView.allowsSelection = NO;
//collectionView.scrollEnabled = NO;
[cell.superview bringSubviewToFront:cell];
[UIView animateWithDuration:2.0 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:.2 options:UIViewAnimationOptionCurveLinear animations:^{
cell.center = CGPointMake(self.view.vWidth/2, self.bannerView.vBottomEdge + collectionViewOffset + 40);
} completion:^(BOOL finished) {
}];
}
I am trying to figure out a way to animate the deletion of a UICollectionViewCell similarly to springboard in iOS 7. The deleted cell should shrink into nothingness and the remaining cells should slide over to fill its place (the sliding is the important part). I have tried:
• Setting the frame of each cell to the frame of the previous cell, like so:
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
CGRect rect = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:i - 1 inSection:0]].frame;
[UIView animateWithDuration:0.2 animations:^{
cell.frame = rect;
}];
But this did not work, as the cells did not move at all.
• Both of the following:
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} completion:nil];
and
[UIView animateWithDuration:0.2 animations:^{
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
}];
But these make the cells crossfade to their required spots, not slide.
I also found this project, which uses the following:
for (int i = index+1; i<[items count]; i++) {
SEMenuItem *item = [items objectAtIndex:i];
[UIView animateWithDuration:0.2 animations:^{
if (i < index + remainingNumberOfItemsInPage) {
int intVal = item.frame.origin.x;
if (intVal %3== 0)
[item setFrame:CGRectMake(item.frame.origin.x+2*item.frame.size.width, item.frame.origin.y-item.frame.size.height-5, item.frame.size.width, item.frame.size.height)];
else
[item setFrame:CGRectMake(item.frame.origin.x-item.frame.size.width, item.frame.origin.y, item.frame.size.width, item.frame.size.height)];
}
[item updateTag:item.tag-1];
}];
}
However, it is not in a UICollectionView, so it does not help me.
Note: I am doing this on an iPad, just in case it matters to you.
Any ideas?
Subclass UICollectionViewFlowLayout. Implement:
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:indexPath]; // might need to replace self with super
attr.transform = CGAffineTransformMakeScale(0, 0);
return attr;
}
In addition to duci9y's answer, (using attr.transform = CGAffineTransformMakeScale(0,0);), the following makes the tiles slide. I can't believe I didn't think of this before.
[self.collectionView performBatchUpdates:^{
[self.collectionView deleteItemsAtIndexPaths:#[indexPath]];
[dataSource removeObjectAtIndex:indexPath.row];
} completion:nil];
I am trying all the stuffs i could like using UIView to animate but in vain.
I need the CollectionView Cells should automatically swipe horizontally after every fixed seconds.
Please help me out with this, as this is the only sole reason my app is waiting its release.
I tried this but in vain.
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
if (collectionView == self.myCV) {
myCollectionView *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MY_CELL" forIndexPath:indexPath];
if (cell == nil)
{
NSArray *xibPath = [[NSBundle mainBundle] loadNibNamed:#"myCollectionView" owner:self options:nil];
cell = [xibPath objectAtIndex:0];
}
// [myCV performBatchUpdates:^{
// [self.myCV reloadData];
// } completion: nil];
[UIView animateWithDuration:0.3f delay:0.0 options:0 animations:^{
[self.myCV scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:indexPath.section inSection:0]
atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
animated:NO];
} completion:^(BOOL finished) {
NSLog(#"Completed");
}];
return cell;
}
Thank You,
*Best Regards.*
If your move code is working then use it in timer function with interval of 1 sec as
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(targetMethod)
userInfo:nil
repeats:YES];
-(void)targetMethod
{
[self.myCV scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:rowIndex inSection:0]
atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
animated:YES];
rowIndex=(rowIndex<noOfRows-1)?(rowIndex+1):0;
}
OR
This could help u better
https://stackoverflow.com/a/13129472/1305001
You should wrap insert/delete/reload operations in a performBatchUpdates:completion: block.
eg :
[collectionView performBatchUpdates:^{
[self.collectionView reloadData];
} completion: nil];
You should then use a timer to call this code periodically. This assumes you also update your data source
I am animating a view over table view when user taps a cell. Although my DidSeclectRowAtIndexPath is getting called when I tap the cell first time but the animation does not take place. On the second tap the animation block gets triggered.
What may be causing this issue?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.ChosenSubCategory=[self.SubCategoryListArray objectAtIndex:indexPath.row];
[self getUserSpecificLevelDetails];
// [self ShowLevelPickerView];
[UIView animateWithDuration:1.0 animations:^{
[self.ChooseLevelView setCenter:CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2)];
[player prepareToPlay];
[player play];
}];
}
Might be because of the threading issue.
Please try the below solution. Hope it works.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
self.ChosenSubCategory=[self.SubCategoryListArray objectAtIndex:indexPath.row];
[self getUserSpecificLevelDetails];
// [self ShowLevelPickerView];
[self performSelector:#selector(performOperation) withObject:nil afterDelay:0];
}
- (void)performOperation
{
[UIView animateWithDuration:1.0 animations:^{
[self.ChooseLevelView setCenter:CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2)];
[player prepareToPlay];
[player play];
}];`
}
How can I achieve the animation where a UICollectionViewCell with flip and grow to show modal view on tap?
Here is what I used in another project and it was working well :
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
if (cell.selected) {
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
[UIView transitionWithView:cell
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
[cell setFrame:self.selectedCellDefaultFrame];
cell.transform = self.selectedCellDefaultTransform;
}
completion:^(BOOL finished) {
self.selectedCellDefaultFrame = CGRectZero;
[collectionView reloadItemsAtIndexPaths:#[indexPath]];
}];
return NO;
}
else {
return YES;
}
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
[cell.superview bringSubviewToFront:cell];
self.selectedCellDefaultFrame = cell.frame;
self.selectedCellDefaultTransform = cell.transform;
[UIView transitionWithView:cell
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[cell setFrame:collectionView.bounds];
cell.transform = CGAffineTransformMakeRotation(0.0);
}
completion:^(BOOL finished) {}];
}
Different things here :
The bringSubviewToFront: message call is used to prevent the cell to animate behind the other cells
We use two properties declared in the controller : selectedCellDefaultFrameand selectedCellDefaultTransform to save the default state of the cell and reinitialize it when deselecting
When deselecting, we call the reloadItemsAtIndexPaths: method of UICollectionView to be sure that the reset of the position is totally complete
Let me know if you have any trouble with this.
Good luck,
I haven't tried the grow animation, but I think I can help with the UICollectionViewCell flip animation.
Try:
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:1.0
delay:0
options:(UIViewAnimationOptionAllowUserInteraction)
animations:^
{
NSLog(#"starting animation");
[UIView transitionFromView:cell.contentView
toView:newView
duration:.5
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
}
completion:^(BOOL finished)
{
NSLog(#"animation end");
}
];
Hope that helps!