Transition of view controllers - from left to right
Solution 1
Usually you would give a storyboardId to the destinationController and call it like this from the sourceViewController:
//push next view
UIStoryboard *storyboard = self.storyboard;
YourViewControllerClass *destVC = [storyboard instantiateViewControllerWithIdentifier:@"StoryboardID"];
[self.navigationController pushViewController:destVC animated:YES];
Optionally, you can do it manually like this:
// Get the views.
UIView * fromView = sourceViewController.view;
UIView * toView = destinationViewController.view;
// Get the size of the view area.
CGRect viewSize = fromView.frame;
// Add the toView to the fromView
[fromView.superview addSubview:toView];
// Position it off screen.
toView.frame = CGRectMake( 320 , viewSize.origin.y, 320, viewSize.size.height);
[UIView animateWithDuration:0.4 animations:
^{
// Animate the views on and off the screen. This will appear to slide.
fromView.frame =CGRectMake( -320 , viewSize.origin.y, 320, viewSize.size.height);
toView.frame =CGRectMake(0, viewSize.origin.y, 320, viewSize.size.height);
}
completion:^(BOOL finished)
{
if (finished)
{
// Remove the old view from its parent.
[fromView removeFromSuperview];
//I use it to have navigationnBar and TabBar at the same time
//self.tabBarController.selectedIndex = indexPath.row+1;
}
}];
** EDIT **
Inverse function (similar to the back button in the navigation controller):
// Get the views.
UIView * fromView = fromViewController.view;
UIView * toView = destViewController.view;
// Get the size of the view area.
CGRect viewSize = fromView.frame;
// Add the to view to the tab bar view.
[fromView.superview addSubview:toView];
// Position it off screen.
toView.frame = CGRectMake( -320 , viewSize.origin.y, 320, viewSize.size.height);
[UIView animateWithDuration:0.4 animations:
^{
// Animate the views on and off the screen. This will appear to slide.
fromView.frame =CGRectMake( 320 , viewSize.origin.y, 320, viewSize.size.height);
toView.frame =CGRectMake(0, viewSize.origin.y, 320, viewSize.size.height);
}
completion:^(BOOL finished)
{
if (finished)
{
// Remove the old view from the tabbar view.
[fromView removeFromSuperview];
}
}];
Solution 2
All of the ViewControllers in my app inherit from MyViewController
which, in addition to some other default behaviours, has this property:
@property(readwrite, nonatomic) BOOL slideFromSide;
And this code:
- (void) presentViewController: (UIViewController*) vc animated: (BOOL) flag completion: (void (^)(void)) completion
{
BOOL slideIn = NO;
if ([vc isKindOfClass: [MyViewController class]])
{
MyViewController *svc = (MyViewController*) vc;
slideIn = svc.slideFromSide;
}
if (slideIn)
{
[self addChildViewController: vc];
[self.view addSubview: vc.view];
CGRect frame = vc.view.frame;
frame.origin.x = frame.size.width;
vc.view.frame = frame;
frame.origin.x = 0;
[UIView animateWithDuration: 0.33
animations: ^{
vc.view.frame = frame;
}
];
}
else
{
[super presentViewController: vc animated: flag completion: completion];
}
}
- (IBAction) backAction: (id) sender
{
if (_slideFromSide)
{
CGRect frame = self.view.frame;
frame.origin.x = frame.size.width;
[UIView animateWithDuration: 0.33
animations: ^{
self.view.frame = frame;
}
completion:^(BOOL finished) {
[self removeFromParentViewController];
}
];
}
else
{
[self dismissViewControllerAnimated: YES completion: nil];
}
}
Then, in the ViewControllers where I want to slide-in, I have:
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName: nibNameOrNil bundle: nibBundleOrNil];
if (self)
{
self.slideFromSide = YES;
// Whatever else you want to do
}
return self;
}
Calling a new ViewController is just like normal:
WhateverViewController *vc = [WhateverViewController alloc] initWithNibName: nil bundle: nil];
[self presentViewController: vc animated: YES completion: nil];
neeraj
Updated on June 04, 2022Comments
-
neeraj almost 2 years
I am NOT using navigation controller, and I am using storyboards.
I have to make a transition from 1 view controller to other, for which I am using segue.
Now I set the segue style to Custom, and in the corresponding class, I override the
perform
method.-(void)perform { UIViewController *sourceViewController = [self sourceViewController]; UIViewController *destinationViewController = [self destinationViewController]; CATransition *transition = [CATransition animation]; transition.duration = 0.25; transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; transition.type = kCATransitionPush; transition.subtype = kCATransitionFromLeft; [sourceViewController.view.layer addAnimation:transition forKey:kCATransition];animated:NO]; [sourceViewController presentViewController:destinationViewController animated:YES completion:nil]; }
But there is also a property of the destination view controller
modalTransitionStyle
.So Right now, the source VC goes from left to right as if it is being pushed, but I want to show that it is being pushed by the destination view controller. Instead, the destination VC does a 'Cover Vertical' by default, and there are only four options available for the
modalTransitionStyle
property, none of which is working for me.I think to make it work, this animation should be added to some superview layer, a superview from which both view controllers have been presented. But there is no such superview..