I'm trying to produce a custom effect when the user presses the default back button (not custom button) of uiviewcontroller's navigation bar. I'm trying to move down a uiview to certain Y position BEFORE popping the view and let the view controller just disappear.
I tried two methods:
Method 1
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[UIView animateWithDuration:0.2 animations:^{
self.cvCell.frame = self.selectedCellFrame;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.75
animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:self.navigationController.view cache:NO];
} completion:^(BOOL finished) {
[self.navigationController popViewControllerAnimated:NO];
}];
}];
}
Method 2:
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
[UIView animateWithDuration:0.2 animations:^{
self.cvCell.frame = self.selectedCellFrame;
} completion:^(BOOL finished) {
CATransition *transition = [CATransition animation];
[transition setDuration:0.75];
[transition setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[transition setType:kCATransitionReveal];
[transition setSubtype:kCATransitionFromLeft];
[transition setDelegate:self];
[self.navigationController.view.layer addAnimation:transition forKey:nil];
}];
}
}
In both the cases the view disappears before the animation on UIView would kick in.
Any suggestions on achieving this?
If you are using Storyboards in your iOS app, you could try to implement a cusom segue animation. You can override the method prepareForSegue:sender: to check if the transaction should occur and the method perform: to bring new view controller on screen. You can then subclass UIStoryboardSegue and enable custom animations in there
iOS Docs
Related
My problem is that I've 2 graphics animation one after the other, but they are done together.
I thought to write a method with completion block, but or I'm doing something wrong, or there is another way to do this.
The animation is a uiview that move out of the screen (closeView) and the default animation of viewcontroller closing.
I want the viewcontroller closes when is over the animation of view.
This is what i've done
- (void)closeViewWithCompletion:(void (^) (BOOL finish))handler {
[self closeView];
handler(YES);
}
-(void) closeView{
[self.myview setFrame:CGRectMake(
-self.myview.frame.size.width
, self.myview.frame.origin.y
, self.myview.frame.size.width
, self.view.frame.size.height
)];
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromRight];
[animation setDuration:.50];
[animation setDelegate:self];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
CALayer *layer = [self.myview layer];
[layer addAnimation:animation forKey:nil];
[UIView animateWithDuration:0.5 animations:^{
[greyMask setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0]];
} completion:^(BOOL finished) {
[greyMask removeFromSuperview];
}];
}
use:
[vc closeViewWithCompletion:^(BOOL finish) {
[navController popViewControllerAnimated:true];
}
];
call your handler block in completionBlock after your closeView Animation finishes.
- (void)closeViewWithCompletion:(void(^)(BOOL finish))handler {
//closeView Animation
[UIView animateWithDuration:duration delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^{
//code for close view animation
} completion:^(BOOL finished) {
handler(YES) //call your handler in completion block
}];
}
[vc closeViewWithCompletion:^(BOOL finish) {
[self.navigationController popViewControllerAnimated:true];
}];
I am working with a custom transition, animation like that of a push.
But when i use this code after my viewcontroller loaded after after animation it just blinks.
Here is the method i used to present my view controller
+(void)leftpresentFrom:(UIViewController *)fromviewcontroller
To:(UIViewController *)toviewcontroller
{
CGPoint newcenter = CGPointMake(480, toviewcontroller.view.center.y);
toviewcontroller.view.center =newcenter;
toviewcontroller.view.clipsToBounds=YES;
[fromviewcontroller.view addSubview:toviewcontroller.view];
[UIView animateWithDuration:.5
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
toviewcontroller.view.center = CGPointMake(160 ,toviewcontroller.view.center.y);
}
completion:^(BOOL finished){
[toviewcontroller.view removeFromSuperview];
[fromviewcontroller presentViewController:toviewcontroller animated:NO completion:^{
}];
}];
}
did you try removing the view after the new controller has been presented?
eg.
[fromviewcontroller presentViewController:toviewcontroller animated:NO completion:^{
[toviewcontroller.view removeFromSuperview];
}];
I am new to iOS. I am trying to change the transition animation in navigation controller to load a new UIView controller from bottom to top, using Segue. I believe it will not be too hard to implement but may be I am not able to understand it.
I could not find any solution in other posts.
Here's the code I've been trying:-
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"alarmSegue"]) {
tab2ViewController *destViewController = segue.destinationViewController;
UIView *destView = destViewController.view;
destViewController.selectionName = #"alarms";
[sender setEnabled:NO];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView animateWithDuration:0.0
delay:0.0
options: UIViewAnimationOptionCurveLinear
animations:^{
[destView setTransform:CGAffineTransformMakeTranslation(0, -1000)];
//[destView setFrame:CGRectMake(0, 440, 400, 45)];
//destView.frame = CGRectMake(0, 0, 320, 460);
}
completion:^(BOOL finished){
[sender setEnabled:YES];
}];
[UIView commitAnimations];
}
}
I just want to implement a SIMPLE transition from bottom to top, using Segue. I want to set some properties of destination controller as well.
Replace the code between [UIView beginAnimations:nil context:nil]; and [UIView commitAnimations]; (including those two lines as well) with the following:
CGAffineTransform baseTransform = destView.transform; //1
destView.transform = CGAffineTransformTranslate(baseT,0,destView.bounds.size.height); //2
[UIView animateWithDuration: 0.5 animations:^{
destView.transform = baseTransform; //3
}];
Make a reference of the original transform.
Push our view down without an animation so we can animate it back up
Set the original transform back to the view. This time, it'll animate
You can further add the delay, options and completion parameters to that UIView Animation method. Xcode will probably help you with the autocompletes on those.
Well you are nearly there.
You need to change two things mainly:
1 Change the initial position of the view. You want the view to appear from bottom to top, so initially your view should be at the bottom. This piece of code should be written before the animation.
[destView setTransform:CGAffineTransformMakeTranslation(0, -1000)];
2 Then you need to slide from bottom to the original position , hence inside the animation block:
[destView setTransform:CGAffineTransformMakeTranslation(0, 0)];
One more suggestion, I guess you are using a newer version of iOS(above iOS4) instead of using animation blocks use UIView's animation method
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
For further info, refer description.
EDIT :
According to your edit on question, you are looking to change the transition animation for NavigationController in the app using storyboard. For that you could use Custom Segue. You will have to create a custom segue, a class that subclasses UIStorySegue and override its perform method like this:
-(void)perform {
//UIViewAnimationOptions options;
UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
UIViewController *destinationController = (UIViewController*)[self destinationViewController];
CATransition* transition = [CATransition animation];
transition.duration = 0.9f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
transition.subtype = kCATransitionFromTop; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[destinationController.view.layer addAnimation:transition forKey:kCATransition];
[sourceViewController presentViewController:destinationController animated:NO completion:nil];
}
You have to change the segue class to this custom segue in storyboard as well, to make it function.
Try using transition effects
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"alarmSegue"]) {
CATransition transition = [CATransition animation];
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = direction;
[self.view.layer addAnimation:transition forKey:kCATransition];
tab2ViewController *destViewController = segue.destinationViewController;
UIView *destView = destViewController.view;
destViewController.selectionName = #"alarms";
[sender setEnabled:NO];
}
}
In my app im showing different screen this way:
info = [[Info alloc]initWithNibName:#"Info" bundle:nil];
[self.view addSubview:info.view];
Info is a subclass of UIViewController, so i just create it and add it as a subview of the current view.
When i want to dismiss it i just do:
[self.view removeFromSuperview];
Im not sure if this is the right way of doing it, but yesterday apple has published on app store another app that do the same to display views.
My question is, how can i animate the transition between views, so when i call addsubview it do the animation?
I tried this:
info = [[Info alloc]initWithNibName:#"Info" bundle:nil];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight
forView:info.view
cache:YES];
[self.view addSubview:info.view];
[UIView commitAnimations];
But its not working, this dont do anything.
It's not the right way to manage view hierarchy. You should use view controller methods for this (addChildViewController: & removeFromParentViewController). Then you can use method transitionFromViewController:toViewController:options:animations:completion: (or something like that) to do various animations.
to add a view controller's view use this
ChildViewController * child = [[ChildViewController alloc] initWithNibName:#"ChildViewController" bundle:nil];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight
forView:info.view
cache:YES];
[self.view addSubview:child.view];
[UIView commitAnimations];
[self addChildViewController:child];
[child release];//for NON ARC
to remove view use this...
for (UIViewController *childVC in [self childViewControllers])
{
[childVC removeFromParentViewController];
}
[self.view removeFromSuperview];// YOU CAN ADD ANIMATIONS HERE
[self removeFromParentViewController];
HOPE this will help you, It is working fine for me....
You can use CATransition for that kind of animation without using navigationcontroller below is the code
Info *infoViewController = [[Info alloc]init];
CATransition *transition = [CATransition animation];
transition.duration = 0.50;
transition.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromRight;
UIView *containerView = self.view.window;
[containerView.layer addAnimation:transition forKey:nil];
[self presentModalViewController:infoViewController animated:NO];
Like this you can animate the view from left to right without using navigationcontroller.
You can give UIView Block Animation a shot. Something like this:
[UIView animateWithDuration:.25 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^
{
requiredView.frame = CGRectMake(0, 300.0, 400.0, 180.0);
} completion:^(BOOL finished)
{
}];
You can set the view's frame and position it outside the viewing co-ordinates and then change the frame accordingly to animate the UIView.
I try to add a subview(which is a subclassed UIViewController's view, consists of several UIButtons and UILabels) to current view, but the animation doesn't work, the subview just appeared without animation.
the code is :
[UIView beginAnimations:nil context:nil];
[UIView setAnimaitonCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationTransition:transition forView:thisPersonViewController.view cache:YES];
[self.view addSubView:thisPersonViewController.view];
[UIView commitAnimations];
it just doesn't work, but if I change forView parameter from the subview (thisPersonViewController.view) to self.view, the self.view did animate, that's curios.
My xcode version is 4.2 and SDK version is 5.0, thx for anyone who offer an solution!
===========THE FOLLOWING CODE WORKS FINE===============
CATransition *trans = [CATransition animation];
[trans setDuration:0.4f];
[trans setType:kCATransitionReveal];
[trans setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[thisPersonViewController.view layer]addAnimation:trans forKey:kCATransitionReveal];
[self.view addSubview:thisPersonViewController.view];
Another annoying question is if I change the CATransition type to kCATransitionFromBottom or something else the animation doesn't work again !
Add thisPersonViewController.view as a subview with a position somewhere off the screen. (i.e. frame x/y coordinate right at the bottom of the screen.)
Do this:
[UIView animateWithDuration:0.5f delay:0.0f options:UIViewAnimationCurveLinear animations:^(void)
{
// Move it to wherever you want to have it.
thisPersonViewController.view.frame = CGRectMake(0.0f, 0.0f, thisPersonViewController.view.frame.size.width, thisPersonViewController.view.frame.size.height);
}
completion:^(BOOL finished)
{
// Do something when it completes the animation if you so desire.
}];