View sizing with setting navigationbar to hidden with push/pop - iphone

So before I push a new viewController onto the stack in a certain view, I set the navigationBar to hidden I notice that it disappears before the next screen gets pushed and the slide animation happens (because I need a UIToolbar at the top).
So question #1: is there a way to push a new view controller and setting the navigationbar to hidden, and not getting the hide animation until after the new view controller is on screen. it looks funny that the navigation bar hides then pushes the new view controller.
Once the new view controller is present, when I pop it off, I set the navigation bar back
[self.navigationController.navigationBar setHidden:NO];
But when it is popped, the navigationbar is not back any more. Is it because this navigationBar is for the current navigationController and not the new one that is being presented after the pop? (question #2)
Question 3: Realizing it isn't showing my navigationBar, in the viewController that gets presented after the pop, in its viewDidAppear, I added
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.navigationController.navigationBar setHidden:NO];
}
which shows the navigationBar, but the view size is incorrect since it seems like once the navigation bar was hidden, the rest of the view took up the empty space, and then the navigationBar is on top of the content. Is there anything I can do about this? Or am I approaching it incorrectly with push and pop?(question #3).
Thanks!

I was running into the very same problem (only in reverse: I was starting from a NavigationBar being hidden and pushing a view where I wanted the NavigationBar visible), and there's actually an extremely easy fix.
Simply replace your calls:
[self.navigationController.navigationBar setHidden:NO];
with
[[self navigationController] setNavigationBarHidden:NO animated:YES];
In my code, I call these statements in the - (void)viewWillAppear:(BOOL)animated methods of each respective View Controller.
I just tried this solution in the order you are using (visible, then hidden), and it seems to work just as well.

Interesting issue. You could try changing the hidden property in viewWillAppear and viewWillDisappear, but it seems like that might not give the desired results either.
Can you present the view controller modally instead of making the navigation bar disappear? If it's the last view controller on the stack, that would be possible. It might also make more sense to the user to see a view controller presented differently. This might indicate to the user that navigating away from this view controller is no longer done with the Back Button. It could be more reasonable than having the navigation bar just disappear.
If you still wanted the view controller to slide in from the right, I don't think it can be done with a modal view controller. But, you could do that by animating a view that fills the screen. (You just add the view with a frame that has origin.x equal to the width of the screen. Then, in the animation, you change origin.x to 0.0. Let me know if you need more detail on this.)
However, I would recommend presenting the view controller in a different manner from the way a view is generally presented by a navigation controller. Because, essentially, you are no longer letting the user navigate away from this view as he/she generally would from within a navigation controller. (So, my response to question #3 would be 'yes'.)

Related

Why do positions of my UI elements change on popViewController?

I recently started using interface builder, the problem i'm facing right now is when i use the back button of navigation controller, my UI elements' y axis go up by roughly 20-30 px, is there some setting i've to use to avoid this problem ? And they go up only when i use pushViewController, when i use popViewController it loads the way i need.
Code i'm using for pushing:
examVC=[[ExampleClass alloc] initWithNibName:#"ExampleClass" bundle:nil];
[[self navigationController] pushViewController:examVC animated:YES];
I'm attaching the images with the question. Please note how label has gone down about 20-30 px.
Why does this happen? What am i doing wrong ?
Thanks for all the help.
Edit : changed the screens for better clarity
I'm using pushing code on the round rect button.
Screen 1:UI elements set in my IB
Screen 2: How it looks when pushed from previous view
Screen 3: How it looks when popped from the "Next View"
My home view controller had the navigation bar hidden, the screen i posted was the second view which comes after the home view. I wanted to hide navigation bar in the first view only, so i had used :
- (void)viewDidDisappear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
[super viewDidDisappear:animated];
}
It caused the problem because i was showing the navigation bar again in viewDidDisappear, so the view would load first then the navigation bar would be shown causing it to overlap.
So i put the same code in viewWillDisappear, which removed the issue. As navigation bar did load before loading of the next view. Now the view loads just like i designed it in interface builder.
Hey I don't know whether it will work for you or not but in your IB change top bar None to Navigation Bar
Then adjust your element accordingly and tun the code.
I tried all of the suggestions here and none of them worked. My UI elements were always lower when popping back to my original view controller. The only thing that fixed this for me was going into my nib file in Interface Builder and turning off Auto Layout.

Seeing a ViewController behind the displayed one

Is it possible to view the viewcontroller behind the displayed one? I have a viewcontroller with a scrollview, which has imageviews added as subviews and would like the view that presented this viewcontroller to be visible behind the presented view controller.
I have set all the views, the viewcontroller view too to have a clear color background, but still there is a black background. when I dismiss the viewcontroller, I see 2 layers being dismissed. one has alpha dropped, the other not.
Is there an easy way to make this effect possible?
Its not possible. When a new view controller is pushed or presented as modal view, the previous view controller will be removed from the display(may be UINavigationController/iOS hides it). The rule is only one view controller would be visible at a time. So you will see the color of your window(the black color you've mentioned) in the background.
What you could do is make a screenshot before displaying the other controller. and send this image to new controller to be displayed as background.
This will only work for static content, but you could do something like the curl display.
You can do this but the truth is what EmptyStack says.
You can use setFrame of the subView and add it on the viewController. Also use below method to set the index of the added View. By default currentView has Index 0.
[self.view insertSubview:myView atIndex:0];
or you can try below methods as per your logic
insertSubview:aboveSubview:
insertSubview:atIndex:
insertSubview:belowSubview:
addSubViews:
bringSubviewToFront:
removeFromSuperview:

Bad animation when dismissing modal UIImagePickerController

I have a UIViewController (A) that modally presents a second view controller (B). Then, that second view controller modally presents a UIImagePickerController (IP). Basically, I have a stack of 2 modal view controllers.
(A) --modally presents--> (B) --modally presents--> (IP)
View controller (A) is the delegate of the image picker, and it dismisses the entire modal stack using:
[self dismissModalViewControllerAnimated:YES];
The problem is with the animation. When dismissing a modal stack like this, the currently visible view should slide off the bottom of the screen, revealing the newly visible view. So in this case, I expect (IP) to slide off the bottom of the screen, revealing the view for (A).
However, what actually happens is this: The image picker view simply disappears, immediately revealing the view for (A), and only the navigation bar animates off the bottom of the screen. The status bar is also left as black translucent instead of transitioning back to a standard gray; this seems to indicate that the image picker normally does some kind of "cleaning up" that isn't being performed when it's dismissed as part of a modal stack.
If I replace the image picker with another generic view controller, the animation works fine. If (IP) is dismissed by (B), the animation also works fine. The problem seems to occur only when dismissing multiple modal view controllers containing UIImagePickerController.
Has anyone seen this before? Any ideas what I might be doing wrong or how to work around this?
Unfortunately, the method dismissModalViewControllerAnimated does not work exactly as you would expect (at least not visually). To achieve what you want, you need to dismiss both modal viewcontrollers in a row, the first non-animated and the second one animated, as described e.g. here.

How to resize view when using UINavigationController setToolbarHidden:animated:

I'm using the UINavigationController toolbar. Before I display it, I resize my views so that they don't get blocked by the toolbar (I set the frame of the current view controller's view to the rect spanning from the bottom of the navigationBar to the top of the toolbar.
But not all of my view controllers have toolbarItems. So, when switching from a view controller that has items (controller A) to one that doesn't (controller B), I want to hide the toolbar. However, when I call setToolbarHidden:animated: in B's viewWillAppear:animated: method, the toolbar animates down during the push transition and shows the UIWindow background behind it.
This also happens in the reverse direction: when transitioning from B to A (via the back button), I want the toolbar to animate in to show A's toolbarItems again, but since A's view doesn't extend to the bottom of the screen, the UIWindow is visible during the pop transition.
That might not have been the best description, so here's a screenshot:
I have tried updating A's frame in its viewWillDisappear:animated: method, but it does strange things, since it seems to be called within the UINavigationController push animation block. Any insight would be appreciated.
Update: I tried hiding the toolbar in B's viewDidAppear:animated: instead, but the results weren't ideal. Using this solution, the toolbar doesn't get dismissed until the push transition completes. Since B doesn't have any toolbarItems, A's items get pushed to the left during the transition, leaving an empty toolbar on the screen before it disappears. Also, when going back to A, the UIWindow background will be visible unless I set the toolbar to visible in B's viewWillDisappear:animated:, which would mean that B has to know that A has toolbarItems.
Maybe the best practice would be to call setToolbarHidden:animated: in B's viewDidAppear?
Or you can change A's frame before pushing B to navigation controller in a pushViewController:animated: method in a custom UINavigationController subclass.
Since I never found a satisfactory solution to this involving animation, I ended up making my views extend down behind the toolbar to avoid showing the window. If your controller's view is a UITableView or UIScrollView, you can set its contentInset appropriately so that your content won't get covered up by the toolbar:
UIEdgeInsets edgeInsets = [[self tableView] contentInset];
if (![[self navigationController] isToolbarHidden]) {
edgeInsets.bottom = CGRectGetHeight([[[self navigationController] toolbar] frame]);
}
[[self tableView] setContentInset:edgeInsets];

Presenting modal view occasionally hides the navigation bar

I've come across this twice now.
Sometimes using the following line of code:
[self.navigationController presentModalViewController:aViewController animated:YES];
displays the view, but the navigation bar is then hidden.
I can write:
[self.navigationController setNavigationBarHidden:NO];
to my hearts content, everywhere I can think of with no effect.
Has anyone ran into this?
Am I doing something silly?
No, I ran into this as well. The problem is that when you present a modal view controller with a UIViewController based class, it does not extend the calling navigation controller's nav bar onto the modal. The modal view covers the entire screen. What I ended up doing to solve the problem was to create a UINavigationController and push the UIViewController based class onto it, and then do presentModalViewController to the navigation controller's instance.
like:
UIViewController *vc = [[UIViewController alloc] init];
UINavigationController *cntrol = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentModalViewController:cntrol animated:YES];
[cntrol release];
That allowed me to have a nav bar at the top.
I am not sure if that will help in your particular case, the only other thing I would suggest is to replicate the behavior of the modal with a UIAnimation that stops 44px below the top of the phone. That would keep the original navigation bar visible.
#HeatMiser shows a great way to get around the "bug" surrounding the inability to display items on the nav bar. I'm not sure, however, if this is strictly a bug in Presentation, since modal operations ought to trump the underlying view's interface theme. Having the modal operation's theme mimic the underlying UI theme is fine, but wrapping the true modal view with a navigation view feels wrong to me (extra view object just to get a little more behavior).
Instead, the following worked for me and gives the same behavior as "New Message" does in the Mail program (on the iPhone).
In IB, place a UIToolBar at the top of the modal screen (mimicking the navigation bar) with "Cancel" and "Save" UIBarButtonItem's and a Flexible Space Bar Button Item in between to get the buttons to align left and right. Then, add a UILabel centered over the UIToolBar (The Font Helvetica, Bold, Size 18 appears to match the Navigation Bar Title). Connect the buttons to IBAction's on the modal's UIViewController, and you're done.
If there is a navigation controller active, then you should just use
[self.navigationController pushViewControllerAnimated:how];
to slide another view controller in, while giving yourself and the user into a consistent user interface complete with 'automatic' back button support.
Once a navigation controller is in use, presenting a modal view controller should only be done to enlarge the usable area on the screen. And then, you should really use a fancy animation to let the user know that you are stepping away from the "task" or "steps" that the navigation controller was embodying.
Maybe this is obvious, but once you're done with the modal view and want to dismiss it, you should do something like this in your modal vc:
[parentController dismissModalViewControllerAnimated:YES];
Where parentController is a reference to the vc from where you are presenting the modal view.