How To Present A view Controller animated from bottom - ios

I need a Transparent view controller that will come to screen from bottom. I want to see presenting view controller Transparent. I have written this code to present .
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
RatingPopVC *ratingVc = [storyboard instantiateViewControllerWithIdentifier:#"RatingPopVC1"];
[self.navigationController presentViewController:ratingVc animated:YES completion:nil];
RateView.m file-
(void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];//[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8];
}

You need to make a category of UIViewController on Navigation.
Make a method in category for transparency.
Please follow below written code in .h file of category
#interface UIViewController (navigation)
- (void)presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;
#end
Go to .M file of category
#import "UIViewController+navigation.h"
#implementation UIViewController (navigation)
- (void)presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
/*
if(SYSTEM_VERSION_LESS_THAN(#"8.0"))
{
[self presentIOS7TransparentController:viewControllerToPresent withCompletion:completion];
} else {
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:viewControllerToPresent animated:YES completion:completion];
}
*/
// viewControllerToPresent.view.alpha=0.7f;
viewControllerToPresent.view.backgroundColor = [UIColor clearColor];
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:viewControllerToPresent animated:YES completion:completion];
}
-(void)presentIOS7TransparentController:(UIViewController *)viewControllerToPresent withCompletion:(void(^)(void))completion
{
UIViewController *presentingVC = self;
UIViewController *root = self;
while (root.parentViewController) {
root = root.parentViewController;
}
UIModalPresentationStyle originalStyle = root.modalPresentationStyle;
root.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:viewControllerToPresent animated:YES completion:^{
root.modalPresentationStyle = originalStyle;
}];
}

you can use CATransition
check it out this may help you
CATransition *animation = [CATransition animation];
[animation setDuration:2];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromTop];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
SecondView *sObj=[[SecondView alloc] initWithNibName:#"SecondView" bundle:nil];
[self.navigationController pushViewController:sObj animated:YES];
[[sObj.view layer] addAnimation:animation forKey:#"SwitchToView1"];

Just add below line of code
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
RatingPopVC *ratingVc = [storyboard instantiateViewControllerWithIdentifier:#"RatingPopVC1"];
ratingVc.view.backgroundColor=[[UIColor blackColor] colorWithAlphaComponent:0.5];//you can set alpha value or Clear Color
ratingVc.modalPresentationStyle = UIModalPresentationCurrentContext;//add this line of code
[self.navigationController presentViewController:ratingVc animated:YES completion:nil];
Hope it helps you..!

Related

How to POP a viewcontroller with custom back UIbutton?

I am using side drawer menu https://github.com/mutualmobile/MMDrawerController
I cannot come to back with custom UIButton.
- (IBAction)doBackAction:(id)sender {
NSArray *viewControllers=self.navigationController.viewControllers;
for (UIViewController *viewController in viewControllers) {
NSLog(#"%#",NSStringFromClass([viewController class]));
UINavigationController *obj=(UINavigationController *)[self.mm_drawerController centerViewController];
}
UINavigationController *nav =
(UINavigationController *)self.mm_drawerController.centerViewController;
[nav popToRootViewControllerAnimated:NO];
[self.navigationController popViewControllerAnimated:YES];
[self.mm_drawerController closeDrawerAnimated:YES completion:nil];
}
i have tried this also https://github.com/mutualmobile/MMDrawerController/issues/195
I cannot make it work.
You might consider setting a global variable (e.a. on a singleton or in a database) which ViewController you came from with viewDidDissapear:
- (void)viewDidDissapear {
Singleton.lastViewController = [self class];
}
From there you can do this to know where you came from (e.a. an IBAction):
// Set your global variable: `NSString` Singleton.lastViewController
[self presentViewController:[[UIStoryboard storyboardWithName:#"Main_iPad" bundle:nil] instantiateViewControllerWithIdentifier:Singleton.lastViewController] animated:YES completion:nil];
I use this for apps that have custom segues and programmed navigation.
Please try this one. May be its help to you
for (UIViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:[CartVC class]])
{
//Do not forget to import CompareCarsVC.h
// CATransition *transition = [CATransition animation];
// transition.duration = 0.5;
// transition.type = kCATransitionFade;
//
// [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController popToViewController:controller
animated:NO];
break;
}
}

Keep first View Controller visible on custom Segue

I have three view controllers that are arranged like snapchat. The main is embedded in a UINavigationController and is in the middle with a view controller on the left and one on the right.
The transition works well, the left/right animation. But in snapchat when you switch to a controller next to the camera or vis versa, the camera will stay visible(not tinted black) on the custom segue. WITH MINE, if I push the second view controller on the stack, the first view controller seems to fade to black as the animation starts when I want it to stay fully visible. Im guessing I have to change something in my custom segue.
#implementation toTheRight
- (void) perform{
UIViewController *sourceViewController = (UIViewController *)self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *)self.destinationViewController;
CATransition *transition = [CATransition animation];
transition.duration = .5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[sourceViewController.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[sourceViewController.navigationController pushViewController:destinationViewController animated:NO];
}
Taken from these two projects then modifying CustomSegue and CustomUnwindSegue as an example.
https://github.com/soleares/SOLPresentingFun
https://github.com/Phillipus/CustomSegue
CustomSegue.m
#import "CustomSegue.h"
#import "SOLSlideTransitionAnimator.h"
#interface CustomSegue()<UIViewControllerTransitioningDelegate>
#property (nonatomic,strong) SOLSlideTransitionAnimator* animator;
#end
#implementation CustomSegue
- (void)perform {
UIViewController *sourceViewController = self.sourceViewController;
UIViewController *destinationViewController = self.destinationViewController;
destinationViewController.transitioningDelegate = self;
destinationViewController.modalPresentationStyle = UIModalPresentationCustom;
[sourceViewController presentViewController:destinationViewController animated:YES completion:nil];
}
/*
Called when presenting a view controller that has a transitioningDelegate
*/
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source
{
self.animator.appearing = YES;
return self.animator;
}
-(SOLSlideTransitionAnimator*) animator
{
if(!_animator)
{
_animator = [[SOLSlideTransitionAnimator alloc] init];
_animator.appearing = NO;
_animator.duration = 0.35;
_animator.edge = SOLEdgeRight;
}
return _animator;
}
#end
CustomUnwindSegue.m
#interface CustomUnwindSegue()<UIViewControllerTransitioningDelegate>
#property (nonatomic,strong) SOLSlideTransitionAnimator* animator;
#end
#import "CustomUnwindSegue.h"
#import "SOLSlideTransitionAnimator.h"
#implementation CustomUnwindSegue
- (void)perform {
UIViewController *sourceViewController = self.sourceViewController;
sourceViewController.transitioningDelegate = self;
sourceViewController.modalPresentationStyle = UIModalPresentationCustom;
[sourceViewController dismissViewControllerAnimated:YES completion:nil];
}
-(SOLSlideTransitionAnimator*) animator
{
if(!_animator)
{
_animator = [[SOLSlideTransitionAnimator alloc] init];
_animator.appearing = NO;
_animator.duration = 0.35;
_animator.edge = SOLEdgeRight;
}
return _animator;
}
/*
Called when dismissing a view controller that has a transitioningDelegate
*/
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
self.animator.appearing = NO;
return self.animator;
}
#end

How to present View Controller modally on app launch?

I've created a screen that ONLY appears the first time that my app is launched; it works great. However, I'd like to present this screen modally on top of my root view controller (EditorsNoteViewController being the screen I want to present modally on first launch). Does anyone know how I would do this? Here is what I have so far:
Appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"])
{
NSLog(#"not first launch");
self.viewController = [[UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"articlesNav"];
self.window.rootViewController = self.viewController;
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
self.viewController = [[UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"articlesNav"];
self.window.rootViewController = self.viewController;
EditorsNoteViewController *vc = [[EditorsNoteViewController alloc]init];
[self.viewController.navigationController presentViewController:vc animated:YES completion:nil];
}
[self.window makeKeyAndVisible];
return YES;
}
I figured out that you'll have to call
[self.window makeKeyAndVisible];
before presenting the view controller
I have read about and encountered this issue many times. A way to completely get around this issue (without any flickering or warnings) is to consider a custom container view controller that will contain your root view controller and your modally presented view controller, as child view controllers. The container view controller can then transition between the two with custom animations, with a very similar effect as present/dismiss.
Let's consider the following container view controller :
#implementation ContainerViewController {
NSMutableArray* stack;
}
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
stack = [NSMutableArray new];
}
return self;
}
- (void) pushViewController:(UIViewController*) viewController {
UIViewController* currentViewController = [stack lastObject];
[stack addObject:viewController];
if (self.isViewLoaded) {
[self addChildViewController:viewController];
[currentViewController willMoveToParentViewController:nil];
viewController.view.frame = CGRectOffset(self.view.bounds, 0, self.view.bounds.size.height);
[self transitionFromViewController:currentViewController toViewController:viewController duration:0.3 options:kNilOptions animations:^{
viewController.view.frame = self.view.bounds;
} completion:^(BOOL finished) {
[viewController didMoveToParentViewController:self];
[currentViewController removeFromParentViewController];
}];
}
}
- (void) popViewController {
UIViewController* currentViewController = [stack lastObject];
[stack removeLastObject];
if (self.isViewLoaded) {
UIViewController* viewController = [stack lastObject];
[self addChildViewController:viewController];
[currentViewController willMoveToParentViewController:nil];
[self transitionFromViewController:currentViewController toViewController:viewController duration:0.3 options:kNilOptions animations:^{
[self.view sendSubviewToBack:viewController.view];
currentViewController.view.frame = CGRectOffset(self.view.bounds, 0, self.view.bounds.size.height);
} completion:^(BOOL finished) {
[viewController didMoveToParentViewController:self];
[currentViewController removeFromParentViewController];
}];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
UIViewController* viewController = [stack lastObject];
[self addChildViewController:viewController];
[self.view addSubview:viewController.view];
[viewController didMoveToParentViewController:self];
}
#end
In your AppDelegate, you can then have something along those lines :
ContainerViewController* viewController = [ContainerViewController new];
[viewController pushViewController: [RootViewController new];
if ([self shouldPresentModalViewController]) {
[viewController pushViewController: [ModalViewController new];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
Somewhere in the modal view controller, you can use the following code to dismiss it:
[((ContainerViewController*) self.parentViewController) popViewController];
Assuming that you have created your EditorsNoteViewController in a storyboard, you should initialise it like this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
EditorsNoteViewController *vc = (EditorsNoteViewController*)[storyboard instantiateViewControllerWithIdentifier:#"EditorsNoteOrWhateverIdentifierYouChose"];
Try to check your NSUserDefaults in your RootViewController -viewDidLoad, and if it is the first time, present the new UIViewController there (So that you don't need to mess around with your AppDelegate).
If you want to present it animated, you can do it in -viewDidAppear instead of -viewDidLoad.

How to use animateWithDuration: when presenting view controller on iOS 7?

I'm currently using the following code in order to present my view controller.
CATransition* transition = [CATransition animation];
transition.duration = 1;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromBottom;
[self.view.window.layer addAnimation:transition forKey:kCATransition];
[self presentViewController:viewController animated:NO completion:nil];
I need to use more complex animation utilizing UIView animateWithDuration method. It is just modal presentation and background view controller should stay there. How can I animate presenting view controller's view?
Update: next version of code :)
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:NULL];
RootViewControllerEx *viewController = (RootViewControllerEx *)[sb instantiateViewControllerWithIdentifier:#"SB_RDVC"];
viewController.transitioningDelegate = self;
viewController.modalPresentationStyle = UIModalPresentationCustom;
[self presentViewController:viewController animated:YES completion:nil];
...
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
...
}
VC in storyboard doesn't have any segue specified, it stays lonely in storyboard :)
You need to use UIModalPresentationCustom as your UIViewController's modalPresentationStyle.
You then need to create a class that conforms to the UIViewControllerTransitioningDelegate and set that your on presentedViewController.
Example
YourViewController *viewController = [[YourViewController alloc] init];
viewController.delegate = self;
viewController.transitioningDelegate = self;
viewController.modalPresentationStyle = UIModalPresentationCustom;
[self.navigationController presentViewController:viewController animated:YES completion:nil];
You must then implement the following method:
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;
Which returns an object that conforms to a UIViewControllerAnimatedTransitioning protocol, that implements the following method:
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIView *inView = [transitionContext containerView];
UIView *toView = [[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey] view];
toView.frame = //CGRectMake(0,0,0,0);
[inView addSubview:toView];
// Use whatever animateWithDuration you need
[UIView animateWithDuration:0.6f delay:0.0f usingSpringWithDamping:0.7f initialSpringVelocity:0.5f options:UIViewAnimationOptionCurveEaseIn animations:^{
// Custom animation here
} completion:^(BOOL finished) {
// IMPORTANT
[transitionContext completeTransition:YES];
}];
}
Always remember to tell the context when a transition is complete, otherwise you'll enter an unstable state.

FirstViewController doesn't work on removing the subview of SecondViewController

First View Controller
I'm using a UIStoryBoard to allow the FirstViewController to add the view of second ViewController as a subview. On removing the sub view the
- (IBAction) btnMoveTo:(id)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"Second"];
vc.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:vc animated:NO];
}
SecondViewController.m
-(void)viewDidLoad{
self.view.opaque = YES;
self.view.backgroundColor = [UIColor clearColor];
}
- (IBAction) withDraw:(id)sender{
[self.view removeWithZoomOutAnimation:2 option:nil];
}
When I access the withDraw Function, the view of the SecondViewController is removed and firstViewController is back. However when I use the button to access the - (IBAction) btnMoveTo:(id)sender function. It doesn't work. Nothing really happens. Any suggestions or help would be greatly appreciated.
Maybe you can try declare the *vc like this:
UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"Second"];
It worked
- (IBAction) withDraw:(id)sender{
[self.view removeWithZoomOViewControllerutAnimation:2 option:nil];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"First"];
vc.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:vc animated:NO];
}
I added another instance of the firstViewController by pointing to its identifier. So it brings back FirstViewController to the top.

Resources