Using CATransition to custom viewcontroller transition animation - ios

I have two viewcontroller A and B. A support portrait and landscape, B only support portrait.The below codes are on A.
UIStoryboard *board = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
B *vcb = [board instantiateViewControllerWithIdentifier:#"B"];
CATransition *a=[CATransition animation];
a.duration = 0.4f;
a.type = kCATransitionMoveIn;
a.subtype = kCATransitionFromTop;
a.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[self.view.window.layer addAnimation:a forKey:#"kTransitionAnimation"];
[self presentViewController:vcb animated:NO completion:nil];
And on B ,i do the dissmiss.
CATransition *a=[CATransition animation];
a.duration = 0.4f;
a.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
a.type = kCATransitionReveal;
a.subtype = kCATransitionFromBottom;
[self.view.window.layer addAnimation:a forKey:#"dismiss"];
[self dismissViewControllerAnimated:NO completion:nil];
It works ok on portrait mode. But it works wrong when i do the bellow steps:
1. Present the B on portrait mode
2. Turn the cellphone to landscape and then click to dissmiss B.
3. The animation was wrong.
Can anybody explain this and how to fix it.I want the B act same as on the portrait mode.

Not sure, I understand your question correctly. Probably you should handle the DeviceOrientation in your Controller A.

Related

dismissViewControllerAnimated not animating ViewController

I want to slide in a ViewController in the screen, and then at some point slide it out and go back to the presenting ViewController.
I use this code from my MainViewController to launch the modal, and then to dismiss it.
Why is the dismiss slide animation not working?
// Present a React Component sliding from the right on top of current ViewController
+ (void)presentSlidingFromRight:(UIViewController*)presented onViewController:(UIViewController*)presenterVC {
CATransition *transition = [[CATransition alloc] init];
transition.duration = 1;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[presenterVC.view.window.layer addAnimation:transition forKey:kCATransition];
[presenterVC presentViewController:presented animated:NO completion:nil];
}
// Dismiss a React Component sliding to the right
+ (void)dismissSlidingToRight:(UIViewController*)presented onViewController:(UIViewController*)presenterVC {
CATransition *transition = [[CATransition alloc] init];
transition.duration = 3;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[presenterVC.view.window.layer addAnimation:transition forKey:kCATransition];
[presenterVC dismissViewControllerAnimated:NO completion:nil];
}
Could you try changing this line:
[presenterVC dismissViewControllerAnimated:NO completion:nil];
for this one:
[presenterVC dismissViewControllerAnimated:YES completion:nil];
Update
Make sure you are calling your static functions on the Main Thread

CATransition working wrong on orientation change before dismissing a NavigationViewController

Here is my code used to present a navigationViewController :
-(IBAction)showFilterView:(id)sender {
FilterViewController *vc=[self.storyboard instantiateViewControllerWithIdentifier:#"FilterViewController"];
UINavigationController *nvc=[[UINavigationController alloc] initWithRootViewController:vc];
CATransition *transition = [CATransition animation];
transition.duration = 0.35;
transition.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromLeft;
UIView *containerView = self.view.window;
[containerView.layer addAnimation:transition forKey:nil];
[self.tabBarController presentViewController:nvc animated:NO completion:nil];
}
And here is my code to dismiss
-(IBAction)back:(id)sender {
CATransition *transition = [CATransition animation];
transition.duration = 0.35;
transition.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromRight;
UIView *containerView = self.view.window;
[containerView.layer addAnimation:transition forKey:nil];
[[self.navigationController presentingViewController] dismissViewControllerAnimated:NO completion:nil];
}
Situation 1 --- Working well in landscape mode
Situation 2 --- Working well in portrait mode
Situation 3 --- Presenting in a portrait mode and dismissing in landscape mode not working properly(extra animation before displaying correct view)
Situation 4 ---Presenting in a landscape mode and dismissing in portrait mode not working properly(extra animation before displaying correct view)
The UIWindow layer has weird rotation properties and any animations you perform aren't guaranteed to correctly detect orientation (and vary with different iOS versions). The easiest way to do what you're trying to is with a custom presentation animation. This is a good writeup of how to do it.

wMemory Warning and application Crash due to poor ViewController handling?

I have a line of viewControllers set in line. The idea is to go through a process of questions etc. If i was to use the already set up way of changing view controller (through button - modal), i would have no problem with memory. I have tried it. However i need to change the views programmatically and not with buttons directly.
When i do this programmatically my memory usage just starts increasing as i go through the views, until eventually i get a Memory Warning and a crash.
To change the viewController i use custom UIStoryBoardSegue and also methods in the viewController files.
Here is how i do it:
Method in View Controller:
-(void)changeViewController
{
CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.timingFunction =[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[self.view.window.layer addAnimation:transition forKey:nil];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"enterInfoSecondViewController"];
[[[[[UIApplication sharedApplication]delegate]window]rootViewController]presentViewController:vc animated:NO completion:nil];
// [self dismissViewControllerAnimated:YES completion:nil];
//[self presentViewController:vc animated:NO completion:nil];
// [self dismissViewControllerAnimated:NO completion:nil];
}
In custom Segue:
-(void)perform
{
UIViewController *srcViewController = (UIViewController *)self.sourceViewController;
UIViewController*destViewController = (UIViewController *)self.destinationViewController;
CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[srcViewController.view.window.layer addAnimation:transition forKey:nil];
[srcViewController presentViewController:destViewController animated:NO completion:nil];
}
......
Somewhere I do it with segue and somewhere with the top method.
What am i doing wrong? i need help please :) Thank you in advance.
If all you need is to trigger the segue programmatically,
why not use -performSegueWithIdentifier:sender: ?

iOS 7 present modal view inside UINavigationController?

My app is setup using a UINavigationController for all of the navigation. I am wanting to use a modal transition to present a specific view controller in the app. The thing is that I want to keep that new VC embedded inside of the navigation controller, but just that one view needs to use a modal animation rather than push.
How can I go about implementing this modal animation/transition on a single view controller within the UINavigationController?
Keep in mind that after this modal animation happens there will be buttons on that page that will proceed to work in line with a standard UINavigationController push animation.
ITviewViewController *vc = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"vc"];
vc.modalPresentationStyle = UIModalPresentationFullScreen;
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:Nil];
Replace the pseudo code with your view controller names.
With iOS7, this is possible using the new custom transitioning API. You can find more information here: http://www.objc.io/issue-5/view-controller-transitions.html
You create an animation controller (interactive or otherwise), and pass it in the appropriate method of the navigation bar delegate. In your animation controller, you perform the custom animation using UIView animation API. In your case, the animation should perform a slide from bottom into place for forward animation, and slide from place to bottom for reverse animation. If you support interactive animation, you can even control the curve of the animation in relation to the finger slide.
Modal view by default is full screen. You need to change presentation style to show navigationBar
EDIT : This only works for iPad. For iPhone you can use MZformsheet or Kentnguyen to get semi modal behavior
MyModalViewController *targetController = [[[MyModalViewController alloc] init] autorelease];
targetController.modalPresentationStyle = UIModalPresentationFormSheet;
targetController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; //transition shouldn't matter
[self presentModalViewController:targetController animated:YES];
targetController.view.superview.frame = CGRectMake(0,44/*navigation bar's height*/,height, width);//it's important to do this after
// use full screen height and width here
targetController.view.superview.center = self.view.center;
Use this line not presentModelViewController
[self presentViewController:vc animated:YES completion:Nil];
Maybe something like this will work for you (self is UINavigationController):
- (void)verticalPushViewController:(UIViewController *)controller
{
[UIApplication sharedApplication].keyWindow.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9];
CATransition* transition = [CATransition animation];
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
transition.duration = 0.3;
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromTop;
[self.view.layer addAnimation:transition forKey:kCATransition];
[self pushViewController:controller animated:NO];
}
- (UIViewController *)verticalPopViewController
{
[UIApplication sharedApplication].keyWindow.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9];
CATransition* transition = [CATransition animation];
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
transition.duration = 0.3;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromBottom;
[self.view.layer addAnimation:transition forKey:kCATransition];
return [self popViewControllerAnimated:NO];
}
The simplest way.
To present
LaunchImageViewController *launchView = [self.storyboard instantiateViewControllerWithIdentifier:#"launchImage"];
[[UIApplication sharedApplication].keyWindow addSubview:launchView.view];
To close. I calling this inside presented(LaunchImageViewController).
[self.view removeFromSuperview];

Showing pushviewcontroller animation look like presentModalViewController

Is it possible to show pushViewController animation look like presentModalViewController but that has background functionality of pushViewController?
If you want to a fade animation, this approach works.
CATransition* transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController pushViewController:gridController animated:NO];
Try this :
UIViewController *yourViewController = [[UIViewController alloc]init];
[UIView beginAnimations: #"Showinfo"context: nil];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[self.navigationController pushViewController: yourViewController animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
[UIView commitAnimations];
For display PushViewConttroler animation as Present below code is working,
For Push
ViewController *VC = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
CATransition* transition = [CATransition animation];
transition.duration = 0.4f;
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer addAnimation:transition
forKey:kCATransition];
[self.navigationController pushViewController:VC animated:NO];
And for POP
CATransition* transition = [CATransition animation];
transition.duration = 0.4f;
transition.type = kCATransitionReveal;
transition.subtype = kCATransitionFromBottom;
[self.navigationController.view.layer addAnimation:transition
forKey:kCATransition];
[self.navigationController popViewControllerAnimated:NO];
There is 1 issue though, that its display light black background when its going up/down,
Working on that, As soon as its done post new code here.
For All Trying in Xamarin (C#) equivalent Code
From Answer by #hardik Thakkar above, Has the issue of Black backgound during animation, rest all good.
For POP
CATransition transition = CATransition.CreateAnimation();
transition.Duration = 0.4;
transition.Type = CAAnimation.TransitionReveal;
transition.Subtype = CAAnimation.TransitionFromTop;
this.NavigationController.View.Layer.AddAnimation(transition, nameof(CATransition));
For Push
CATransition transition = CATransition.CreateAnimation();
transition.Duration = 0.4;
transition.Type = CAAnimation.TransitionReveal;
transition.Subtype = CAAnimation.TransitionFromBottom;
this.NavigationController.View.Layer.AddAnimation(transition, nameof(CATransition));
You should consider doing something like:
ViewController *myVC = [[ViewController alloc] initWithFrame:OFF_SCREEN];
[navigationController pushViewController:myVC animated:NO];
where OFF_SCREEN is some CGRect below the screen, like (0, 481, 320, 480). Then use an animation block to adjust the viewcontroller's view's frame.origin to be (0, 0). You would probably want to do the animate block in viewDidLoad or viewDidAppear.

Resources