presentViewController:animated:completion wont Animate - ios

this is my first question so please go easy!!
I have an iOS app that has 5 tab bars, each of which contains a Navigation controller. It seems that no matter where I call presentViewController:animated:completion from, I get no animation from the transition, the presented view controller just appears on screen!
This is also happening with my UIImagePickerController that I am presenting from one of my tabs. No presenting animation, but when i dismiss it it DOES animate away!
Here is a sample of the code, sent from a code generated tab bar button, with its action hooked up to a method which simply does this..
UserRegistrationViewController *userRegistration = [[UserRegistrationViewController alloc] init];
userRegistration.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:userRegistration animated:YES completion:nil];
If anyone has ANY ideas of things that I could try I would be most grateful!

I'm assuming that you want your animation to occur during the transition between tab bar presses. If so, you have little control over that animation, as the tab bar manages the transitions for you. It looks like you're trying to achieve a cross fade between tab presses. Although you really can't fade out the old view controller, you can easily make the new view controller fade in when it appears:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//Set the view to transparent before it appears.
[self.view setAlpha:0.0f];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
//Make the view fade in. Set Opaque at the end for a performance boost.
[UIView animateWithDuration:0.5f
animations:^{
[self.view setAlpha:1.0f];
[self.view setOpaque:YES];
}];
}
Note that the tab bar is already presenting view controllers. You should not try to present the view controllers yourself. Let the tab bar manage this for you; that's what it's for.

Related

I want to make a custom view that behaves like an actionsheet come up in an iPad app

I have the main View Controller, which is embedded in a Navigation Controller.
I want to make another view pop up and take up just the middle of the screen, so it basically looks like an action sheet. To make this view pop out, there is a button on the navigation bar (called "Unlock").
I made a new UIViewController, and gave it a new class called CustomModalViewController. Then I put a UIView inside this on the storyboard.
Am I on the right track? What should I do next? Should I embed this CustomModalViewController inside the original Navigation Controller? And perhaps then use this code somewhere:
- (void)showLoginView{
[UIView animateWithDuration:.5 animations:^{
customModalView.frame=CGRectMake(0, 225, CustomModalView.frame.frame.size.width, CustomModalView.frame.frame.size.height);
}];
}
- (void)hideLoginView{
[UIView animateWithDuration:.5 animations:^{
customModalView.frame.frame=CGRectMake(0, 480, CustomModalView.frame.frame.size.width, CustomModalView.frame.frame.size.height);
}];
}
I'm new to objective c and Xcode, and it's still weird to me how all of the files come together.
UIActionSheet disables the remaining screen. I advice you to do the same. So your way using UIViewController subclass would be an appropriate way. You should place your action buttons in the bottom of your controller's view.
You can set a semi-transparent view backgroundColor to view of the customViewController to achieve some visuality like UIActionSheet. You can easily show a modal view controller like:
[self presentViewController:customViewController animated:YES completion:^{
// do something when opened, if you need
}];
And hide like:
[self dismissViewControllerAnimated:YES completion:^{
// do something when closed, if you need
}];
As it can be seen, you don't have to deal with frames. In the manner of controlling, you can implement some delegate methods, something like CustomViewControllerDelegatein your main view controller, so you can be aware of what happened in your customViewController.

Navigation bar jumps out from under status bar?

I have a button in my main view controller that pushes a navigation controller with an embedded view controller using a segue.
When the new view controller is presented, the navigation bar on it briefly appears under the status bar. (The status bar is not hidden.) The contents (which are relative to the top layout guide) are in the correct location. As soon as the animation is complete, it fixes itself.
When the view is dismissed again, the same thing happens: the main view controller briefly overwrites the status bar. For the main view controller, this is a little more significant as it's based on a UITableViewController; the entire table jumps. Again, when the animation is complete the view controller fixes itself.
I've tried turning off translucency on the navigation bar, but it only makes the problem more obvious. All of this works as expected on iOS 6.
I've uploaded a minimalist test case here: https://github.com/tewha/FlipTest
Another simple trick is do this:
In the MasterViewController
When is preparing for Segue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
[UIView transitionWithView:self.navigationController.view
duration:0.75
options:UIViewAnimationOptionTransitionFlipFromRight
animations:nil
completion:nil];
}
And when Unwind the AboutViewController
- (IBAction)aboutUnwind:(UIStoryboardSegue *)segue {
[UIView transitionWithView:((UIViewController *)segue.sourceViewController).view
duration:0.75
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:nil
completion:nil];
}
This is a bug in the layout system of iOS7. I found that reducing the height of the navigation controller's view (not the pushed view controller's!) by the status bar height and placing it in y = status bar height will help a lot, but there will still be a small flicker where the status bar "merges" with the navigation controller.
As a side not, see if the bug still exists in iOS7.1b1.
There is a Problem in the ios 7 with navigation bar ,Navigation bar appear over the views or showing gap between the nav bar and view , You can solved this problem with the help of following code
There has been a new property introduced in iOS 7 that lets you adjust the layout behavior as in previous versions of iOS. this code in your view controller, and you should be good The space your navigation bar takes up should be accounted for automatically
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
Answer obtained from iOS 7 navigation bar jumping / stretching upon viewDidAppear
This is a bug in UK kit. Avoid using the standard methods
'performSegueWithIdentifier' or 'presentViewController'
Here I transition from one controller to another, then transition back in the delegate callback, using UIView transition animations.
-(void)photoButtonPressed:(NSNotification*)notification
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Media"
bundle:nil];
UINavigationController *navCon = [storyboard instantiateInitialViewController];
PhotoCaptureViewController *controller = navCon.viewControllers.firstObject;
controller.delegate = self;
CustomTabBarViewController *tabBarController = (CustomTabBarViewController*)self.tabBarController;
[UIView transitionWithView:self.navigationController.view duration:0.75 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
[tabBarController.parentViewController addChildViewController:navCon];
[tabBarController.parentViewController.view addSubview:navCon.view];
} completion:^(BOOL finished) {
[navCon didMoveToParentViewController:tabBarController.parentViewController];
}];
}
-(void)photoCaptureViewController:(PhotoCaptureViewController *)controller dismissButtonPressed:(UIButton *)dismissButton
{
CustomTabBarViewController *tabBarController = (CustomTabBarViewController*)self.tabBarController;
[UIView transitionFromView:controller.navigationController.view toView:tabBarController.view duration:1 options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) {
[controller.navigationController willMoveToParentViewController:nil];
[controller.navigationController removeFromParentViewController];
[controller.navigationController.view removeFromSuperview];
}];
}
This is a great read about container views Khanlou's blog post

How to navigate inside a UINavigationController which is inside a UITabBarController?

I have a project that is a tab-bar controller. Each tab usually has a UINavigationController. The problem I have is this: I need a new tab with alot of navigation (roughly 30 navigation items grouped into 4-8 groups. Problem: My navigation bar is already full (can't use the navigation controller (or bar). What I need is navigation below the navigation bar (which has a global search bar and other global icons filling it). How can I implement this best?
What I have now: I have created a UIScrollView just under the navigation bar to serve as my "hand-rolled" navigation bar. It's a scrollView because I don't know (going forward) how many "groupings" of navigation items I will have (currently only 4). Each of these groups is represented by a UIButton, some of which should immediately present a view, and others which present a popover with further navigation items, which when selected will present a view.
Problem: I want a "content view" under my navigation view mentioned above, where I can present content based on the user's navigation choices. I have to support iOS 5.0, so I can't use the storyboard container view (unfortunately). I will have 3 types (maybe more later) of content views I will present, that I would like to create as individual view controllers and then push the appropriate one as it's selected in my navigation mentioned. Is there a 3rd party navigation controller I can use? Do I have to "roll my own"? Any advice would be greatly appreciated.
Here is a "slapped-together" picture of what I need to achieve:
I would make what you're calling the content view a subview of your main view, and use it as the view to which you will add a childViewController's view. If you haven't already read up on custom container controllers, you should do so, but the basic way of using them is like this.
The controller's whose view you show in your question would be the custom container controller. You could load up an initial controller in the viewDidLoad method, then switch the controller in your subview (I'm calling it self.containerView) in response to the user choosing something from your scroll bar:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UIViewController *initial = [self.storyboard instantiateViewControllerWithIdentifier:#"InitialVC"];
[self addChildViewController:initial];
[initial.view.frame = self.containerView.bounds];
[self.containerView addSubview:initial.view];
self.currentController = initial;
}
-(void)switchToNewViewController:(UIViewController *) cont {
[self addChildViewController:cont];
cont.view.frame = self.containerView.bounds;
[self moveToNewController:cont ];
}
-(void)moveToNewController:(UIViewController *) newController {
[self.currentController willMoveToParentViewController:nil];
[self transitionFromViewController:self.currentController toViewController:newController duration:.6 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{}
completion:^(BOOL finished) {
[self.currentController removeFromParentViewController];
[newController didMoveToParentViewController:self];
self.currentController = newController;
}];
}
This should give you the basic idea. I took this from one of my test projects, so it will probably need a little tweaking.

iOS: custom segue and presentViewController not working as expected

I'm using a custom segue which looks like this:
#implementation ModalPushSegue
- (void)perform {
UIViewController *fromController = self.sourceViewController;
UIViewController *toController = self.destinationViewController;
UIView *fromView = fromController.view;
UIView *toView = toController.view;
CGPoint centerStage = toView.centerStage;
toView.center = toView.rightStage;
[fromView.window addSubview:toView];
[fromController addChildViewController:toController];
[UIView transitionWithView:toView
duration:0.5 options:0
animations:^{
toView.center = centerStage;
}
completion:nil];
}
This works well in that the view is slide on from the right as expected and the controller is added to the controller hierarchy.
But later in the added controller I do this:
[self presentViewController:anotherController animated:YES completion:nil];
I would expect this to slide the new controller's view up the screen ala modal style. But what happens instead is the the new view doesn't appear. And when I later remove this controller, it's view flashes up and slides off the screen, leaving a black background instead of the view that was originally there.
I've been playing around with this for a while and if I change the code to
//[self presentViewController:oauthController animated:YES completion:nil];
[self.view addSubview:oauthController.view];
[self addChildViewController:oauthController];
Then the view appears as expected, although not resized.
My problem appears to be with the way that the segues setup the hierarchy vs the way that presentViewController does things. I've done lots of reading and searching but so far have not been able to get a clear picture of exactly what is going on.
I've also played around with using presentViewController in the segue but instead of laying the new view over the old one, the screen goes black and the new view then slides on.
Any help appreciated.
Set a Storyboard ID on your destination view controller (in the storyboard), then try the following code:
AnotherController *viewC = [self.storyboard instantiateViewControllerWithIdentifier:#"AnotherController"];
ModalPushSegue *segue = [[ZHCustomSegue alloc] initWithIdentifier:#"coolSegueName" source:self destination:viewC];
[segue perform];

UIModalPresentationFormSheet, dim is missing

I am trying to display a modal viewController in an iPad app using the UIModalPresentationFormSheet view style. I am looking to produce something similar to the Mail app's new message UI/animation.
There are two things that are not behaving correctly:
The modal viewController that is presented always animates to y=0, i.e. to the very top of the
view and not some pixels below the status bar as it does in the mail app.
The documentation says:
UIModalPresentationFormSheet The width
and height of the presented view are
smaller than those of the screen and
the view is centered on the screen. If
the device is in a landscape
orientation and the keyboard is
visible, the position of the view is
adjusted upward so that the view
remains visible. All uncovered areas
are dimmed to prevent the user from
interacting with them.
However, in my case there is no dimming and I can still interact with the parentView below the modalViewController.
The controller that presents the modalView I do this:
AddNewItemViewController *newItemViewController = [[AddNewItemViewController alloc] initWithNibName:#"AddNewItemViewController" bundle:nil];
[self presentModalViewController:newItemViewController animated:YES];
[newItemViewController release];
In the viewController being presented I do this:
- (void)viewDidLoad {
[nameField becomeFirstResponder];
[self setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self setModalPresentationStyle:UIModalPresentationFormSheet];
[super viewDidLoad];
}
I hope someone can help me out.
Is there some other properties I need to set on the parent and modalViewController?
Is the viewDidLoad not the right place to do this setup?
Thanks in advance:)
You set the transition and presentation styles when you create the modal view, before you call presentModalViewController. Remember, the view that creates the modal view 'owns' that object. You want the owner to set these properties because you might implement this modal view elsewhere in the app and want different transition or presentation styles. This way, you set it each time as appropriate.
AddNewItemViewController *newItemViewController = [[AddNewItemViewController alloc] initWithNibName:#"AddNewItemViewController" bundle:nil];
newItemViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:newItemViewController animated:YES];
[newItemViewController release];
You're right in calling becomeFirstResponder in viewDidLoad.

Resources