transition causes views to change from black to clear - ios

I am using the following code to pop a navigation controller from one view controller to a second.
-(void)viewProfile :(UIButton *)sender{
NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray: self.navigationController.viewControllers];
ProfileViewController *newVC = [[ProfileViewController alloc] initWithNibName:#"ProfileViewController" bundle:nil];
[allViewControllers insertObject:newVC atIndex:0];
self.navigationController.viewControllers = allViewControllers;
CATransition* transition = [CATransition animation];
transition.duration = 0.2f;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[self.navigationController.view.layer addAnimation:transition
forKey:kCATransition];
[self.navigationController popViewControllerAnimated:NO];
}
The code works quite well. The one flaw is on the transition the view controller coming or ProfileViewController appears black. Then over the course of the animation it brightens to the default value, meanwhile the view controller calling this function becomes black.
How do I prevent this shading and just have the views always have their default colour throughout the transition?

Related

IOS/Objective-C/Storyboard: Custom Segue from Left to Right Creating Black Bar Between View Controllers

I have subclassed UIStoryboardSegue to create a Left to Right Segue. The segue works, however, there is a black vertical bar or background that is momentarily visible between the two View Controllers that mars the effect. (I want the segue to look like a normal right to left show segue but in the opposite direction). Does anyone know what could be causing this or how to get rid of it? Here is my code:
#import "customSegue.h"
#import "QuartzCore/QuartzCore.h"
#implementation customSegue
-(void)perform {
UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
UIViewController *destinationController = (UIViewController*)[self destinationViewController];
CATransition* transition = [CATransition animation];
transition.duration = .25;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
transition.subtype = kCATransitionFromLeft; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[sourceViewController.navigationController.view.layer addAnimation:transition
forKey:kCATransition];
[sourceViewController.navigationController pushViewController:destinationController animated:NO];
}
#end
Edit:
I thought I would collect some the suggested fixes I have found although none are working for me.
Set the background color of the presenting view controller to white
Set self.definesPresentationContext = YES; on the presenting view controller or check "Defines Context" for the VC in storyboard from accepted answer here.
Specify the context as follows:
UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
UIViewController *destinationController = (UIViewController*)[self destinationViewController]
[sourceViewController presentViewController:destinationController animated:NO completion:nil];
from accepted answer here.
What you're seeing is the view's changing opacity near the beginning and end of the animation, so the "black bar" you're seeing is actually the backing window. While it might not be perfect, a quick fix is to change the background color of your window to match the background color of your destination view controller (then set it back after the transition completes if needed).
Here's your code example with the modifications necessary:
-(void)perform {
UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
UIViewController *destinationController = (UIViewController*)[self destinationViewController];
CATransition* transition = [CATransition animation];
CGFloat animationDuration = 0.25f;
transition.duration = animationDuration;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
transition.subtype = kCATransitionFromLeft; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
transition.fillMode = kCAFillModeForwards;
[sourceViewController.navigationController.view.layer addAnimation:transition
forKey:kCATransition];
// hold onto the previous window background color
UIColor *previousWindowBackgroundColor = sourceViewController.view.window.backgroundColor;
// switch the window background color to match the destinationController's background color temporarily
sourceViewController.view.window.backgroundColor = destinationController.view.backgroundColor;
// do the transition
[sourceViewController.navigationController pushViewController:destinationController animated:NO];
// switch the window color back after the transition duration from above
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(animationDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// make sure we still have a handle on the destination controller
if (destinationController) {
destinationController.view.window.backgroundColor = previousWindowBackgroundColor;
}
});
}
Here's an example of the transition slowed down to 2seconds:
Slowed down transition
And the animation at 0.25 as you have it in your code:
Your speed transition

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

how to implement popover controller in storyboard, custom segue

This is mouli, I'm implementing a custom segue for pushing (with animation) from firstview to second view, its work fine. but iam not getting back from secondview to firstview with same animation. Here the first screen appears with out animation. please give some suggestion. Thanks in advance. following is my code for push from first to second.
UIViewController *sourceViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
NSLog(#"%#",sourceViewController);
sourceViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
UIViewController *destinationController = (UIViewController*)[self destinationViewController];
NSLog(#"%#",destinationController);
CATransition* transition = [CATransition animation];
transition.duration = 0.6;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
transition.subtype = kCATransitionFromRight; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[destinationController.view.layer addAnimation:transition forKey:kCATransition];
[sourceViewController presentViewController:destinationController animated:NO completion:nil];
Do the dismiss in opposite way, since your are doing a custom animation other that the provided one, it doesn't remember the animation of presentation. So while you are dismissing you need to apply the opposite custom animation too.
I would suggest you to create a Category for animations and use them in the whole project easily..

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];

Resources