custom animation in setCollectionViewLayout:animated: to enlarge the selected cell - uicollectionview

I'm changing layouts when selecting a cell in a uicollectionview and have added a custom animation to the collectionview layer
currently I'm using this code:
[self.collectionView performBatchUpdates:^{
CATransition *transition = [CATransition animation];
transition.duration = 0.5f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionMoveIn;
[self.collectionView.layer addAnimation:transition forKey:nil];
[self.collectionView setCollectionViewLayout:self.horizontalPagingLayout animated:NO];
self.galleryInHorizontalScrollMode = YES;
[self.collectionView setPagingEnabled:YES];
} completion:^(BOOL finished) {
[self reloadData];
}];
I would like to change the animation style (transition.type) such that the selected cell will "grow" (or shrink) to the size of the final cell size defined in the collectionview layout
How can this be done?
I've tried solutions as suggested here but they looked very poor

Related

UIActivityIndicatorView keeps animating preceding CATransition pushViewController

I'm trying stop the animation on my UIActivityIndicatorView in the same method that I push a view controller using a CATransition fade.
Instead of stopping the animation, then fading to the next view controller, the UIActivityIndicatorView contiues animating throughout the entire fade, no matter how long I set the duration.
Any ideas how I can get the spinning to stop, then push/fade in the same method?
- (void)pushView:(NSNotification *)notification {
[self.activityIndicator stopAnimating];
NextViewController* nextViewController = [[NextViewController alloc] init];
CATransition *transition = [CATransition animation];
transition.duration = 1.5f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:nextViewController animated:NO];
}
Edit 1
Along the same lines as David's answer, I was able to successfully stopAnimating if I used dispatch_after and delayed for a fraction of a second. Is there a better way to accomplish this?:
- (void)pushView:(NSNotification *)notification {
[self.activityIndicator stopAnimating];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.0001 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void){
NextViewController* nextViewController = [[NextViewController alloc] init];
CATransition *transition = [CATransition animation];
transition.duration = 1.5f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:nextViewController animated:NO];
});
}
I've run into something similar to this before. What you are running is called Synchronous Execution. In synchronous execution, the UI is not updated until the compiler terminates the function, a.k.a. the }. How do you get around this? Simple. Just run any methods to update the UI in an Asynchronous dispatch:
- (void)pushView:(NSNotification *)notification {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
dispatch_async(dispatch_get_main_queue(), ^(void){
[self.activityIndicator stopAnimating];
});
NextViewController* nextViewController = [[NextViewController alloc] init];
CATransition *transition = [CATransition animation];
transition.duration = 1.5f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:nextViewController animated:NO];
});
}
Whoops! I forgot to put the other code in a plain dispatch! Try the edited code and it should work!
This way the [self.activityIndicator stopAnimating]; is run on a priority thread, while the rest of the code in the function is run in the default priority thread, effectively running the code at the same time, the way you would expect it to.
Cheers!

screen flash when addsubview by CATransition

Many people use this method to add animation on switching views. When I try to add animation effect on adding a subview, the view always flash once。 The reason is that the view add subview immediately at the beginning, after that, the animation starts.
CATransition *transition = [CATransition animation];
transition.duration = 0.35;
transition.removedOnCompletion = NO;
transition.fillMode = kCAFillModeForwards;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromBottom;
transition.delegate = self;
[[animationView layer] addAnimation:transition forKey:#"switchView"];
OtherViewController *otherController = [[OtherViewController alloc]init:cityID];
self.myOtherViewController = otherController;
[otherController release];
[self.view insertSubview:myOtherViewController.view atIndex:1];
What's the reasons of problem? How to implement the animation of loading new view without flash?
After modified fillMode to kCAFillModeBoth, it works.
transition.fillMode = kCAFillModeForwards;

How to animate removeFromSuperview

I animated the appearance of my subview with:
CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionReveal;
[webView.layer addAnimation:transition forKey:nil];
[self.view addSubview:webView];
But now I want to remove my subView. How can I add animation to do this? Like other CATransition? When to add this? Before or after addSubview?
Well you could do the animation first and on the animationEndListener call removeFromSuperView
[UIView animateWithDuration:0.5
delay:1.0
options: UIViewAnimationOptionCurveEaseOut
animations:^{
yourView.alpha = 0;
}completion:^(BOOL finished){
[yourView removeFromSuperview];
}];

iOS switch between views of same viewController

I have three views on same viewController and I need to switch beetween them with transitions. Which is the best method to do it? Thank you
Well I am not sure if you have made the question clear .I Guess you want to show the views one at a time.In that case :-
1>You can add the views in a horizontal UIScrollView with its frame size equal to the screen or whatever area you want(width should be equal to width of screen..shown 1 at a time) along with a UIPageControl.
2>The other way is to use the Methods:-
[self.view bringSubViewToFront:yourSubView];
[self.view sendSubViewToBack:yourSubView ];
according to your requirements.
3>You can use Animation to switch between views.
[UIView animateWithDuration:0.7
delay:1.2
options: UIViewAnimationCurveEaseOut
animations:^{
CGRect frame=assignAframeToSwitch;
yourView.frame = frame;
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
OR
_Weak CATransition *transition;
transition = [CATransition animation];
transition.delegate=self;
transition.duration = 0.75;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[[viewcontroller layer] addAnimation:transition forKey:#"transition"];
CATransition is the best way to animate transition
CATransition* trans = [CATransition animation];
[trans setType:kCATransitionPush];
[trans setDuration:0.5];
[trans setSubtype:kCATransitionFromBottom];
// code to change the view//
CALayer *layer = rootViewController.view.layer;
[layer addAnimation:trans forKey:#"Transition"];
Hope it helps.
if you use this bellow code for animation for transitions and then just need to hide and show the view on button click event...
CATransition *animation = [CATransition animation];
[animation setDelegate:self];
[animation setType:kCATransitionFromBottom];
[animation setDuration:1.0];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:
kCAMediaTimingFunctionEaseInEaseOut]];
[[yourViewControllers layer] addAnimation:animation forKey:#"transitionViewAnimation"];
hope,this help you..
:)
The fastest easiest way to do this is with the built in block based UIView transition animations. Just look at the documentation for UIView. Its way simpler than the CATransition methods.

iphone sdk MapView update users location

I've successfully put together a mapview with a pin annotation representing the users current position that updates at a set interval. When the location manager updates the user's position, the pin annotation disappears and reappears at the new location. Has anyone played with getting the current user's GPS location to update through the use of an animation, like what is done in Apple's offical mapping application? If so, I'd love some pointers to get this to work. Thanks!
Solution 1:
First, you need to make your view controller implement MKMapViewDelegate if it doesn't already.
Then, implement this method:
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
MKAnnotationView *aV;
for (aV in views) {
CGRect endFrame = aV.frame;
aV.frame = CGRectMake(aV.frame.origin.x, aV.frame.origin.y - 230.0, aV.frame.size.width, aV.frame.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.45];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[aV setFrame:endFrame];
[UIView commitAnimations];
}
}
Add your annotations to the MapView and when they are added, this delegate method will be called and will animate the pins from top to bottom as they are added.
The values for timing and positioning can be changed a little bit but I've tweaked it to make it look best/closest to the traditional drop (as far as I've tested).
Solution 2:
Alternatively, if you're making a MKAnnotationView subclass, you can use didMoveToSuperview to trigger the animation. The following does a drop that ends in a slight 'squish' effect
#define kDropCompressAmount 0.1
#implementation MyAnnotationViewSubclass
...
- (void)didMoveToSuperview {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform"];
animation.duration = 0.4;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, -400, 0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:#"transform"];
animation2.duration = 0.10;
animation2.beginTime = animation.duration;
animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
animation2.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DMakeTranslation(0, self.layer.frame.size.height*kDropCompressAmount, 0), 1.0, 1.0-kDropCompressAmount, 1.0)];
animation2.fillMode = kCAFillModeForwards;
CABasicAnimation *animation3 = [CABasicAnimation animationWithKeyPath:#"transform"];
animation3.duration = 0.15;
animation3.beginTime = animation.duration+animation2.duration;
animation3.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
animation3.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
animation3.fillMode = kCAFillModeForwards;
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = [NSArray arrayWithObjects:animation, animation2, animation3, nil];
group.duration = animation.duration+animation2.duration+animation3.duration;
group.fillMode = kCAFillModeForwards;
[self.layer addAnimation:group forKey:nil];
}
Hope this helps!
PK