Hidden NavigationBar reappears after app enters foreground - ios

I have a UITableViewController inside a navigationController. I have code that hides the navigationBar (sets its frame.origin.y to a negative value, thereby sending it offscreen) when I scroll the tableView. The navigationBar is successfully hidden, but when I leave the app by tapping the home button and then launch the app into the foreground, the navigationBar is back with frame.origin at (20, 0) (x = 20 since the status bar is visible), and the tableView pushed down the screen (with frame.origin back to (64, 0) in portrait).
Any ideas on how to prevent the navigationBar from reappearing upon the app entering the foreground would be much appreciated.

I think You didn't choose the best practise to hide navigationBar as most of "interal views" are positioned by it's superview automaticaly. The thing is that when you scroll, the navigationBar is moved off the screen...but when the app enters foreground all views are layouted (checkout UIView setNeedsLayout and layoutSubviews) and this moves the novigationBar back to it's position where it belongs to (y=0). There are few other options that you can use:
1) use UINavigationController's setNavigationBarHidden:(animated:) in viewWillAppear: and viewWillDisappear:. More info here SO: how to hide navigationbar when i push from navigation controller?
2) if you want to leave the space behind the navigationBar use (in viewDidLoad or methods from #1):
self.navigationController.navigationBar.alpha = 0;
3) move your code for setting frame in method viewDidLayoutSubviews of you controller (iOS 5+). Every time you scroll in UITableViewControler layoutSubviews method is called (and viewDidLayoutSubviews too). But I wouldn't recommend this solution.

Instead of setting the frame you can use the below code to hide the Navigation bar.
[self.navigationController setNavigationBarHidden:YES];
Hope this will help you. Happy coding :)

Related

Keyboard flashes from opaque to transparent upon push

I have a view embedded in a navigation and tab bar controller. When a button is pressed, it pushes to (shows) the next view and I programmed the keyboard to immediately show for the first text field [textField becomeFirstResponder].
However, the keyboard will be opaque instantly then turn transparent in a little less than half a second. This happens no matter the keyboard type or keyboard look. I have no idea what is causing this, and I cannot find any answers anywhere else.
Other details: the navigation bar is translucent, and the bottom bar is hidden on the view we push to. The background is an image. This problem does not occur if I remove [textField becomeFirstResponder] and have the user just select the text field, but that is not what I am trying to do.
I have a similar scenario and also ran into this issue.
I am push-segueing between view controllers, and the keyboard has to stay up during the segue (textField.becomeFirstResponder() is called in viewWillAppear(_:)). The view controllers' background is white, but the keyboard look is Dark. During the segue, the keyboard is black, and then turns gray as soon as the segue finishes.
I came up with a workaround for that - it works if you want to have the keyboard opaque-ish at all times.
Add an empty UIView to the view controllers where you want to show the keyboard instantly, and set the backgroundColor of the view to match your keyboard's look (black for Dark, white for Light). Pin that view to left, right and bottom edges of the view controller's safe area superview. Add a height constraint to it equal to 0 and make an IBOutlet for it.
In your view controller, subscribe to KeyboardWillShow and KeyboardWillHide notifications and control the height constraint of the view you created - make it match the keyboard's frame height (the keyboard's frame end).
You will still see that during the segue, the keyboard stays opaque, but when the segue finishes and keyboard transparency kicks in, the effect is much less visible.
Ideal scenario for me would be to be able to turn off the transparency of the keyboard completely, but I don't think it's possible. I also think there is no way to make the keyboard non-opaque during the segue, so the only option is to make it look opaque at all times.

tableHeaderView preserves state when popping viewController except ContainerViewController

I have a tableViewController with a tableHeaderView. When I'm at the top of the tableView and I scroll the tableView up slightly the tableHeaderView is hidden and can reappear again by scrolling down slightly. This is the default behaviour.
When I push to a viewController then pop back to the tableViewController, the state of the tableHeaderView is preserved. i.e., if it was hidden it remains hidden and if it was visible it remains visible.
However, for some reason when I push to another viewController that has a containerView and then pop back, the tableHeaderView always displays. Even if it was hidden before pushing.
The Issue was that I had checked Hide Bottom Bar On Push in storyboard on the viewController that I was pushing to. For some reason this caused the tableHeaderView to always display when popping back. Unchecking this fixed the problem. Instead the tabBar can be hidden in viewDidLoad of the pushed viewController with the following:
self.tabBarController?.tabBar.isHidden = true
Hope this will help somebody.

Navigation bar prompt & height resize animation

Good day!
I have an embedded navigation bar in my app.
mainView is a ViewController with tableView in it.
On first launch there is no prompt text on navigation bar. When you get to options (second view controller) you can set a text to your main views prompt. So after you do so, returning from "Options" to mainView triggers nice and smooth animation on navigation bar increasing its height and prompt text appears.
When i launch the app for the second time, where prompt text is loaded, the text is ok, the size is ok, but the animations of height resize start to get glitchy when switching views, navigation bar height jumps from big to small w/o animation, although text appears to dissolve as usual.
Here is an example of where i switch views in a loaded app:
If i go to options view controller and again set the prompt text -> animation of height increase between views gets fine.
I'm sure i am missing something at launch, something like tableView.reloadData() in viewDidLoad, but for navigation bar.

Using Autolayout, unable to move the navigation bar down 20px

I have a UITabBarController which has four tabs. One of those tabs opens a my results screen (a UITableViewController).
On showing this screen, I want to move the UINavigationBar down 20px (to make room for a custom UIStatusBar which I show on all screens).
On all my other screens, I add some code to the viewWillAppear method to change the self.navigationController.navigationBar.frame.origin.y to 20.
but these are all "non-root" screens (i.e. a pushed view with a back button).
However on THIS screen the UINavigationBar must be initially visible, even though it is the root view. I use the same code, but it doesn't move the view down.
I'm assuming autolayout is moving it back into position, so I tried adding this code into viewWillLayoutSubviews and viewDidLayoutSubviews. But when I do this the navigationbar doesn't move down until the first time the tableview is scrolled.
What do I need to do to force the navigationBar to move down (and stay down) before the screen appears?
Are you using storyboards? Set the Y in storyboards to 20, Make your viewcontroller implement UINavigation bar, then add this code:
-(UIBarPosition)positionForBar:(id<UIBarPositioning>)bar{
return UIBarPositionTopAttached;
}
This will tell the app that the navigation bar is to be attached, it will remain at 20px but extend the background all the way up.. So essentially it'll look like it's at y = 20.

Animate Controls down with change to UINavigationBar

I have a UINavigationController with standard UINavigationBar. When presenting certain UIViewControllers and orientations, the UINavigationBar may or may not appear and it may or may not have a prompt element. This means that the bar height changes frequently.
I have some subviews below the UINavigationBar set with NSLayoutConstraints to topLayoutGuide. It generally lays out as expected, adjusting vertical position of the subviews appropriately based on the height of the UINavigationBar. What it does not do is move the subviews at times when the UINavigationBar is animated after the view is already displayed.
Specifically, coming from a state with UINavigationBar hidden, transition to a UIViewController which does not hide the navigation bar to one which does. The view displays, then navigation bar animates into place. The subviews do not move down. If I rotate the device, every things lays out appropriately again. Only when animating the navigation bar in and out or to display/hide the prompt I not find a hook to reevaluate the constraints.
I tried [self.view updateConstraints] and [self.view updateConstraintsIfNeeded] in various places such as viewDidAppear, viewDidLayoutSubviews. Nothing seems to update that topLayoutConstraint.
I am familiar with edge restraints, translucent navigation bar and other various methods of keeping the entire view from appearing under the navigation bar. I do want to keep view full size and I want the translucent bar so these are not solutions for me. It seems the constraints should handle this automatically, hence the "auto" in auto layout.
To simplify, for recreation, UINavigationController with rootViewcontroller showing normal navigation bar with just a title. In viewDidLoad of the next presented viewController I have [self.navigationContoller setPrompt:self.myPrompt]. The view is presented, when the prompt is set, the navigation bar grows larger. Some labels below the bar are set with relation to topLayoutGuide, which places them correctly initially. I expect they would move down when the bar grows. Rotate device back and forth, they now layout correctly. Pop the viewController and push back to top, repeats as above.
So, it turns out it was all me. After trying all manner of forcing layout updates in all sorts of ways, the solution was to move the [myView setPrompt:myPrompt] out of viewDidLoad and call it in viewDidAppear instead.
Works completely as expected. Navbar grows, subviews shift and shrink as needed. Now I have to hunt down all the experimental code I plastered everywhere trying to do it wrong.

Resources