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
Related
My requirement is simple , i just need to add a TableCell with rightRowAnimation and scroll to it. It happens as long as i am with within tableView height , as i cross the height of tableView to add cell further , it adds cell but displays no animation when scrolling to it.
Attached is a simple project with a UITableView for reference , Appreciate your help !!
Sample Project with a simple UItableView and Add Button
Code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell1"];
BOOL myBool = indexPath.row%2 == 0;
if(myBool){
cell.backgroundColor = [UIColor redColor];
}else{
cell.backgroundColor = [UIColor whiteColor];
}
cell.textLabel.text = [self.dataArray objectAtIndex:indexPath.row];
return cell;
}
-(IBAction)addTapped:(id)sender {
[self.dataArray addObject:#"New Object"];
// [_tableView beginUpdates];
[_tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:self.dataArray.count-1 inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
// [_tableView endUpdates];
[_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.dataArray.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
Use bellow method for the animation.
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.alpha = 0;
cell.layer.transform = CATransform3DMakeScale(0.5, 0.5, 0.5);
[UIView animateWithDuration:0.7 animations:^{
cell.alpha = 1;
cell.layer.transform = CATransform3DScale(CATransform3DIdentity, 1, 1, 1);
}];
}
change what ever your requirements
you can try this to animate row put in table.
-(void)viewWillAppear:(BOOL)animated
{
dispatch_async(dispatch_get_main_queue(), ^{
[UIView transitionWithView:yourtablename
duration:5.1f
options:UIViewAnimationOptionTransitionFlipFromTop
animations:^(void) {
[yourtablename reloadData];
} completion:NULL];
});
}
also you can change animation style.
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
i am trying to create a custom animation for the deletion of table rows by overriding the deleteRowsAtIndexPaths method. i created the custom insert animation successfully and tried to reverse the animation for the deletion part but i get some errors: Assertion failure in -[UITableView _endCellAnimationsWithContext:]
and
NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.(rows after update must be equal to rows before the update).
If i don't override the deleteRows method and use tableView's default delete method, everything works fine, but not with my own method.
Here is the overriden method written in my tableViewController class:
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths
withRowAnimation:(UITableViewRowAnimation)animation
{
[[super tableView] insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates]; // Populates UITableView with data
[self.tableView beginUpdates];
for (NSIndexPath *indexPath in indexPaths) {
__block UITableViewCell *cell = [[super tableView] cellForRowAtIndexPath:indexPath];
if (cell) { // If indexPath isn't visible we'll get nil here
// Custom animation
CGRect frame = cell.frame;
frame.origin.x = cell.frame.size.width;
cell.frame = frame;
frame.origin.x = 0;
void (^animationsBlock)() = ^{
cell.frame = frame;
};
if ([[UIView class] respondsToSelector:
#selector(animateWithDuration:delay:usingSpringWithDamping:
initialSpringVelocity:options:animations:completion:)]) {
[UIView animateWithDuration:0.9
delay:0
usingSpringWithDamping:0.5
initialSpringVelocity:0
options:0
animations:animationsBlock
completion:NULL];
} else {
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveEaseIn
animations:animationsBlock
completion:NULL];
}
}
}
}
deleteRowsAtIndexPathsMethod:
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths
withRowAnimation:(UITableViewRowAnimation)animation
{
[[super tableView] deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates]; // Populates UITableView with data
[self.tableView beginUpdates];
for (NSIndexPath *indexPath in indexPaths) {
__block UITableViewCell *cell = [[super tableView] cellForRowAtIndexPath:indexPath];
if (cell) { // If indexPath isn't visible we'll get nil here
// Custom animation
CGRect frame = cell.frame;
frame.origin.x = 0;
cell.frame = frame;
frame.origin.x = cell.frame.size.width;
void (^animationsBlock)() = ^{
cell.frame = frame;
};
if ([[UIView class] respondsToSelector:
#selector(animateWithDuration:delay:options:animations:completion:)]) {
[UIView animateWithDuration:0.9
delay:0
options:UIViewAnimationOptionCurveEaseIn
animations:animationsBlock
completion:NULL];
} else {
[UIView animateWithDuration:0.9
delay:0
options:UIViewAnimationCurveLinear
animations:animationsBlock
completion:NULL];
}
}
}
}
Edit: this code is inside a method, that runs whenever i modify a cell's object. I modify an object and save it to core data, then i retrieve all the updated objects using [self populateData], then i want to run the animations: delete the old cell and insert the new updated cell somewhere at the bottom of the tableView
[coreDataStack saveContext];
[self populateData];
[self.tableView beginUpdates];
int oldIndex = indexPath.row;
int newIndex = newIndexPath.row;
if(oldIndex<newIndex){
[self deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationRight];
[self insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationTop];
} else if (oldIndex>newIndex) {
[self deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationRight];
[self insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationBottom];
} else {
[self.tableView reloadRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationMiddle];
}
[self.tableView endUpdates];
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'm switching between layouts in a uicollectionview using this code
-(void)setHorizontalLayout:(BOOL)layout
{
if (layout == YES)
{
[self.collectionView performBatchUpdates:^{
[self.collectionView setCollectionViewLayout:self.horizontalPagingLayout animated:NO];
[self.collectionView setPagingEnabled:YES];
self.galleryInHorizontalScrollMode = YES;
} completion:^(BOOL finished) {
[self.collectionView reloadData];
}];
}
else {
[self.collectionView performBatchUpdates:^{
[self.collectionView setCollectionViewLayout:self.galleryLayout animated:NO];
self.galleryInHorizontalScrollMode = NO;
[self.collectionView setPagingEnabled:NO];
} completion:^(BOOL finished) {
[self.collectionView reloadData];
}];
}
return;
}
but after I change from one layout to the other I am getting the [0,0] indexpathed cell set as the uicollectionview's background. I suspect something with the layer is messed up. And looking over the call stack all looks fine. I can't see any calls to animations that may be messing with the layer.
Any way to invalidate this? what could cause it?
I'm not sure on why this behavior happens but when I invalidated the layout before changing the layout all works as expected:
[self.collectionView performBatchUpdates:^{
***[self.collectionView.collectionViewLayout invalidateLayout];***
[self.collectionView setCollectionViewLayout:self.horizontalPagingLayout animated:NO];
} completion:^(BOOL finished) {
[self.collectionView reloadData];
}];