Animation of scrolling in collectionview in ios - ios

I have one one collectionview in that I have 10 images loaded from webservice. I want to autoscroll that imageview from 1st to last position and then last to 1st position continuously whenever that page appears.
I use below method
-(void)scrollSlowly
{
CATransition *transition = [CATransition animation];
transition.duration = 4.0f;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[transition setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[UIView animateWithDuration:5.0f
delay:3.0f
options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
animations:^{
[self.CollectionView setContentOffset:CGPointMake(CGFLOAT_MAX ,0)];
}
completion:nil];
[self.CollectionView.layer addAnimation:transition forKey:#"transition"];
}
-(void)scrollSlowlyToPoint
{
self.CollectionView.contentOffset = self.scrollingPoint;
// Here you have to respond to user interactions or else the scrolling will not stop until it reaches the endPoint.
if (CGPointEqualToPoint(self.scrollingPoint, self.endPoint))
{
[self.scrollingTimer invalidate];
}
// Going one pixel to the right.
self.scrollingPoint = CGPointMake(self.scrollingPoint.x+1, self.scrollingPoint.y);
}
I want to autoscroll horizontally in Objective-C. thanks in advance

Create a custom UICollectionViewCell class, create and connect an outlet for image view.
In .h file:
NSMutableArray *imgArr;
NSInteger testIndexPath;
I guess you can implement the datasource methods for UICollectionView.
In cellForItemAtIndexPath add this line after adding images to the imageview
testIndexPath=indexPath.row;//this will give you the indexPath for cell
Now add this two methods in your .m file:
-(void)autoScroll{
CGFloat point = self.collectionVw.contentOffset.x;
CGFloat lo = point + 1;
[UIView animateWithDuration:0 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.collectionVw.contentOffset = CGPointMake(lo, 0);
}completion:^(BOOL finished){
if (testIndexPath==8)
{
[self autoScrollReverse];
}
else{
[self autoScroll];
}
}];
}
-(void)autoScrollReverse{
CGFloat point = self.collectionVw.contentOffset.x;
CGFloat lo = point - 1;
[UIView animateWithDuration:0 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.collectionVw.contentOffset = CGPointMake(lo, 0);
}completion:^(BOOL finished){
if(testIndexPath == 0){
[self autoScroll];
}else{
[self autoScrollReverse];
}
}];
}
//Call [self autoScroll] in your viewDidLoad

Better way to scroll index from top to bottom and bottom to top.
This will move to index 10 means scroll top to bottom
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:9 inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
For again scroll bottom to top which move to index 0
[UIView animateWithDuration:3
delay:0.1
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
}
completion:nil];
You can also set scrolling from top to bottom in UIVIew animation like above.
Set the first method in ViewWillAppear and set second method in ViewDidAppear if you need animation for every time page appear

Please apply this one. May be its help to you
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyCollectionViewCell" forIndexPath:indexPath];
[UIView animateWithDuration:0.2 animations:^{
cell.transform = CGAffineTransformMakeTranslation(0.0, -50);
}];
[self delayBy:0.5 code:^{ // call block of code after time interval
[UIView animateWithDuration:0.3 animations:^{
cell.transform = CGAffineTransformIdentity;
}];
}];
return cell;
}

This may help solve your problem:
int maxDelay = 4;
int delayInSeconds = arc4random() % maxDelay;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//your codes//
});

Related

Bounce Animation on UITableViewCell

When the UITableView loads I want its first cell to bounce from the Right side, so It indicates the User that they can swipe right to delete a cell.
How can I do this ?
My code so far:
note: In the following code I am just making the cell to blink, but what I actually want is the cell to bounce.
-(void) tableView:(UITableView *) tableView willDisplayCell:(UITableViewCell *) cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
//row number on which you want to animate your view
//row number could be either 0 or 1 as you are creating two cells
//suppose you want to animate view on cell at 0 index
if(indexPath.row == 0) //check for the 0th index cell
{
// access the view which you want to animate from it's tag
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:1];
UIView *myView = [self.tableView cellForRowAtIndexPath:indexPath];
NSLog(#"row %ld",(long)indexPath.row);
// apply animation on the accessed view
[UIView animateWithDuration:5
delay:2
options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveEaseInOut animations:^
{
[myView setAlpha:0.0];
} completion:^(BOOL finished)
{
[myView setAlpha:1.0];
}];
}
}
If I understand this correctly, you wish to bounce the cell from left to right?
Get a reference to the cell's contentView:
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:1];
UIView *contentView = [self.tableView cellForRowAtIndexPath:indexPath].contentView;
Now there are many ways to 'bounce' this contentView. One way would be to use an animation block like this:
CGRect original = contentView.frame;
CGRect bounce_offset = original;
original.origin.x -= 100.0f;
What we do here, is remember the original frame, and decide how far we want our bounce to reach in the animation block. Then we can animate for example doing something like this:
[UIView animateWithDuration:0.5f delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
contentView.frame = bounce_offset;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.75f initialSpringVelocity:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^{
contentView.frame = original;
} completion:^(BOOL finished) {
}];
}]
You could also use autoreverse options, this 'a' way to do it though. Let me know what your thoughts are!

Fade in and fade out animation is too slow

I made an animation, fade in and fade out on a cell. When I press the cell(a button on the entire cell) the action is delegate via a protocol on a collectionView and pops to another controller (detailController).
The cell
- (IBAction)cellButtonPressed:(id)sender {
[self fadeIn];
}
-(void)fadeIn {
[UIView animateWithDuration:0.5
delay:0.0
options:0.0
animations:^{
self.coverAlbumPhoto.alpha = 0.0f;
self.shadowView.alpha = 0.0f;
self.mountainBorderImageView.alpha = 0.0f;
} completion:^(BOOL finished) {
[self fadeOut];
}];
}
-(void)fadeOut {
[UIView animateWithDuration:0.5
delay:0.0
options:0.0
animations:^{
self.coverAlbumPhoto.alpha = 1.0f;
self.shadowView.alpha = 1.0f;
self.mountainBorderImageView.alpha = 1.0f;
} completion:^(BOOL finished) {
if ([self.delegate respondsToSelector:#selector(tapCellButtonAtIndexPath:)]) {
[self.delegate tapCellButtonAtIndexPath:self.indexPath];
}
}];
}
Collection View
(void)tapCellButtonAtIndexPath:(NSIndexPath *)indexPath {
ArtworkModel *artworkModel = (ArtworkModel *)[listOfArtworks objectAtIndex:indexPath.row];
FBWorkDetailsViewController *dvc = [[FBWorkDetailsViewController alloc] initWithArtwork:artworkModel];
FBLeftMenuViewController *left = [[FBLeftMenuViewController alloc] init];
MFSideMenuContainerViewController *container = [MFSideMenuContainerViewController
containerWithCenterViewController: dvc
leftMenuViewController: left
rightMenuViewController:nil
withHeader: YES];
[container.titleLabel setText:#"WORK DETAILS"];
[self.navigationController pushViewController: container animated: YES];
}
The problem is that the animation is TOO SLOW. Can anybody explain me why? Thanks.
You have 2 animations, each with a duration of .5 seconds. That gives a total duration of 1 second. If you want it to be faster, use shorter durations. A total animation time of .2 to .3 seconds is probably a good place to start, so try backing down the duration of each step to 0.15 seconds (0.3 seconds total).

UICollectionView cell didselect flip animation, View is missing

UICollectionView cell flip animation on didSelect method should flip with Detailed information on the of the clicked index cell and if user want to go original view should be able to see on cell.
I am using
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:1.0
delay:0
options:(UIViewAnimationOptionAllowUserInteraction)
animations:^
{
[UIView transitionFromView:cell.contentView
toView:cell.contentView
duration:.5
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
}
completion:^(BOOL finished)
{
}
];
In your code the animation removes your from view and show the to view.So, in the collection if the content view is removed then how it come back.
So, don't remove the view, just hide it.
Please use the below code
CVCell* cell1 = (CVCell *)[collectionView cellForItemAtIndexPath:indexPath];
[UIView transitionWithView:cell1.contentView
duration:5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
if (cell1.isred) {
cell1.isred = NO;
cell1.greenview.hidden = NO;
cell1.redView.hidden=YES;
} else {
cell1.isred = YES;
cell1.greenview.hidden = YES;
cell1.redView.hidden=NO;
}
} completion:nil];
greenview is first view and redview is second which are added on the cell.
Now when fliped first greenview is shown and redview is hidden and next time viceversa
You can try other animation
CATransition *animation = [CATransition animation];
animation.delegate = self;
animation.duration = 2.6f;
animation.timingFunction = UIViewAnimationCurveEaseInOut;
animation.fillMode = kCAFillModeForwards;
animation.startProgress = 0.1;
animation.endProgress = 1.0;
animation.removedOnCompletion = YES;
animation.type = #"cube";//---
animation.subtype = (cell1.isred)?kCATransitionFromLeft:kCATransitionFromRight;
[CATransaction setCompletionBlock:^{
if (cell1.isred) {
cell1.isred = NO;
cell1.greenview.hidden = NO;
cell1.redView.hidden=YES;
} else {
cell1.isred = YES;
cell1.greenview.hidden = YES;
cell1.redView.hidden=NO;
}
}];
[cell1.contentView.layer addAnimation:animation forKey:#"Cameraanimation"];

iOS 7 photos app like custom UIViewController Transition

I am a bit new to iOS development. I am working on an app that has about 5,000 visual data points, organized in categories. I want to present them in a UICollectionView with very tiny UICollectionViewCells. When a user taps on something in a category, the category zooms in with the selected cell in focus. Pretty much like how the "Photos" tab of the iOS 7 Photos app works: Years > Collections > Moments.
How do I go about implementing a custom transition like that? Are there any open-source libraries already written for accomplishing this?
If you can't find any library, try to play with this code I wrote for custom animations. You can specify a start point, an end point, start scale and end scale of a view that you want to zoom and scale in or out. See below an example how I use it. The point is to use a fake view to push it with animation, then push and pop your real view without animation. viewobj is set to fade in from alpha 0 to alpha 1, zoomableView will scale from the point/scale you give as parameter to the final position you set it in your storyboard/xib. Hope it will help.
# you can create a category vor UIView and add these methods
- (void) addSubView:(UIView*)viewObj animateFromPoint:(CGPoint)point zoomableView:(UIView*)view minScale:(CGSize)scale completion:(void (^)(void))completionBlock{
CGPoint center = view.center;
[view setTransform:CGAffineTransformMakeScale(scale.width, scale.height)];
viewObj.alpha = 0;
view.center = point;
[self addSubview:viewObj];
[self addSubview:view];
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
view.center = center;
[view setTransform:CGAffineTransformMakeScale(1.0, 1.0)];
viewObj.alpha = 1;
}
completion:^(BOOL fin){
if(completionBlock)
completionBlock();
}];
}
- (void) removeFromSuperviewAnimateToPoint:(CGPoint)point zoomableView:(UIView*)view minScale:(CGSize)scale completion:(void (^)(void))completionBlock{
CGRect startFrame = view.frame;
self.alpha = 1;
[self.superview addSubview:view];
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
view.center = point;
[view setTransform:CGAffineTransformMakeScale(scale.width, scale.height)];
self.alpha = 0;
}
completion:^(BOOL fin){
[self removeFromSuperview];
[view removeFromSuperview];
[view setTransform:CGAffineTransformMakeScale(1, 1)];
view.frame = startFrame;
[self addSubview:view];
if(completionBlock)
completionBlock();
}];
}
And to use them:
# your did select item at index path:
self.itemDetails = [self.storyboard instantiateViewControllerWithIdentifier:#"ItemDetailsVC"];
ItemDetailsVC* itd = [self.storyboard instantiateViewControllerWithIdentifier:#"ItemDetailsVC"];
__weak UIViewController* wself = self;
[self.view addSubView:self.itemDetails.view animateFromPoint:self.zoomedFrom zoomableView:self.itemDetails.viewZoomable minScale:CGSizeMake(0.371134, 0.371134) completion:^{
[wself.navigationController pushViewController:itd animated:NO];
}];
self.addSubviewIsUp = YES;
# back button of the view you added:
[self.navigationController popViewControllerAnimated:NO];
# viewdidapear of your main screen
if(self.addSubviewIsUp){
[self.addVc.view removeFromSuperviewAnimateToPoint:CGPointMake(160, 75) zoomableView:self.addVc.zoomableView minScale:CGSizeMake(0.01, 0.01) completion:^{
}];
}
self.addSubviewIsUp = NO;

Text Animation within didSelectRowAtIndexPath:?

I'm using an MCSwipeTableViewCell so the idea is that the user swipes it left or right to complete actions. However the user may not always be familiar with this action so when they tap the cell (expecting to select it) I want the text to briefly flash a short instruction then return to the original text.
I've been on this for days and keep coming back to it with no luck. I've tried using the completion block, playing about with the delays, all sorts but the animation seems to complete so quickly you don't actually see the change, what am I doing wrong?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
MCSwipeTableViewCell *cell = (MCSwipeTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
Station *station = self.recentStations[indexPath.row];
[UIView animateWithDuration:0.5 animations:^{
//code to fade the text out
CATransition *animation = [CATransition animation];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.type = kCATransitionFade;
animation.duration = 0.35;
[cell.textLabel.layer addAnimation:animation forKey:#"kCATransitionFade"];
//instructions to appear briefly
cell.textLabel.text = #"Swipe left to set alarm or right to remove";
//nested animation to revert text after a 1.5 second delay
[UIView animateWithDuration:.05 delay:1.5 options:UIViewAnimationOptionCurveEaseIn animations:^{
//code to fade the text back in
CATransition *animation = [CATransition animation];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.type = kCATransitionFade;
animation.duration = 0.35;
[cell.textLabel.layer addAnimation:animation forKey:#"kCATransitionFade"];
cell.textLabel.text = station.name;
} completion:nil];
}];
}
You're using duplicate nested animation APIs. Give the below code a try.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
MCSwipeTableViewCell *cell = (MCSwipeTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
Station *station = self.recentStations[indexPath.row];
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
cell.textLabel.alpha = 0.0f;
} completion:^(BOOL finished) {
//instructions to appear briefly
cell.textLabel.alpha = 1.0f;
cell.textLabel.text = #"Swipe left to set alarm or right to remove";
[UIView animateWithDuration:0.5 delay:1.5 options:UIViewAnimationOptionCurveEaseInOut animations:^{
cell.textLabel.alpha = 0.0f;
} completion:^(BOOL finished) {
cell.textLabel.alpha = 1.0f;
cell.textLabel.text = station.name;
}];
}];
}
That code will have the new text instantaneously swap out the old text and appear - you can probably figure out how to add more animations to prevent this if desired.

Resources