How do I present a transparent UINavigationController + root modally? - ios

In my TabBarController, I'm presenting a UINavigationController as a modal. Once I present it, I'd like everything to be transparent (including the navigation bar). However, I'd like everything after the root controller to be opaque.
let transVC = self.storyboard?.instantiateViewControllerWithIdentifier("TransparentViewController") as! TransparentViewController
transVC.delegate = self
transVC.view.backgroundColor = UIColor.clearColor()
transVC.modalPresentationStyle = .CurrentContext
self.navController = UINavigationController(rootViewController: transVC)
self.navController?.modalPresentationStyle = .CurrentContext
self.presentViewController(self.navController!, animated: false, completion: nil)
Later, I will push other view controllers onto the stack. I want them to be opaque.
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
self.navController!.pushViewController(messageVC, animated: false) //should be opaque
If there is no sure way to do this, maybe we can take a screenshot of the app and set it as the background, as a workaround? How would I do that?

No, taking a screenshot is not necessary for a modally presented view controller to have a transparent background. Just present the segue using the presentation style of .OverFullScreen or .OverCurrentContext, rather than .CurrentContext, and ensure the view controller has a clear colored background.
Also, make sure you are setting the modalPresentation style of the navigation controller since that is what you are presenting, and therefore what will be used by the modal segue:
navController?.modalPresentationStyle = .OverFullScreen
Auto-(un)hiding Navigation Bar
For the navigation bar to be hidden on the navigation controller's root view controller, I would subclass the root view controller so that when it appears, the navigation bar is hidden. When it disappears, the navigation bar should be unhidden.
In TransVC:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: true)
}
Because it can be animated, setNavigationBarHidden integrates seamlessly with pushViewController. Alternatively, you could move the line that unhides the navigation bar to the viewWillAppear method in the view controller you are presenting.

Related

Navigation pushViewController is not working

i have login view controller. when usersingin i' showing popup for that i
refereed
https://www.youtube.com/watch?v=S5i8n_bqblE i can achieved that.
popup had button when i click the button navigation to next view controller
but its now working when i am clicking that action is performing but its not navigating to next view controller wher i did mistake
Singin
class DigitalGateViewController: NANavigationViewController
{
#IBAction func singin(_ sender: UIButton)
{
let lv = NAViewPresenter().activityVC()
self.present(lv, animated: true)
}
}
this is popupviewcontroller
class ActivityViewController: NANavigationViewController {
#IBAction func okbuttonclick() {
let dv = NAViewPresenter().myGuestListVC()
// self.navigationController?.pushViewController(dv, animated: true)
}
}
its not push to textview controller in swift
When you present a view controller, its presented modally and is not pushed onto the previous navigation controller's stack. Hence, you tried to call self.navigationController?.pushViewController(), it doesn't work, because self i.e. NAViewPresenter().myGuestListVC() isn't embedded in a navigation Controller.
If you want to push the new VC onto the previous stack, you will have to dismiss the presented pop up and then push. The easiest way to do this is to use a delegate method.
Edit:
if you want to create a new navigationController, you can do something like this :
let navController = UINavigationController(rootViewController: NAViewPresenter().myGuestListVC())
present(navController, animated: true)
After presenting the navController, you can use self.navigationController.push method henceforth.
The reason why its not pushing because you are presenting it modally not pushing on the navigation stack and so it wont have any navigationController. If you want to push from your modal popup, you can access the property presentingViewController on your modal object and try to push it on navigationController from there.
self.presentingViewController?.navigationController?.pushViewController(myVC, animated: true)
dismiss(animated: true, completion: nil)

swift how to push back to navigation view control

I have several view controllers and they are very complexed.
MainVC (embed with tab bar controller)
FriendListVC
ChatRoomUpperVC (embed with navigation view controller)
ChatRoomVC (NavigationViewController with embed in ChatRoomUpperVC) (only shows the tab bar)
ChatRoomQuestionVC (pushed from ChatRoomVC) (only shows the navigation bar)
MatchedWaitVC (pushed from ChatRoomQuestionVC) (hide both tab and navigation bars)
ChatVC (pushed from MatchedWaitVC) (only shows the navigation bar)
SettingVC
What I have to do is when I click the back button from the ChatVC, I should back to ChatRoomVC and show the tab bar on the bottom only.
I tried the code below but it shows the black screen and there is no tar bar neither.
override func willMove(toParentViewController parent: UIViewController?) {
if parent == nil
{
var viewControllers = navigationController?.viewControllers
viewControllers?.removeLast(3)
navigationController?.setViewControllers(viewControllers!, animated: true)
self.navigationController?.isNavigationBarHidden = true
self.tabBarController?.tabBar.isHidden = false
}
}
I guess you can use following hack to achieve what you want. In the viewDidLoad method of the ChatVC do:
override func viewDidLoad() {
super.viewDidLoad()
if let root = navigationController?.viewControllers.first {
navigationController?.viewControllers = [root, self]
}
}
This will remove the inbetween view controllers that are between ChatVC and ChatRoomVC. Now popping back (e.g. using the standard back button, or swiping from the left edge of the screen) will jump back directly to the ChatRoomVC.
EDIT
To show the tabBar again in the ChatRoomVC, add this to the viewDidAppear:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.tabBarController?.tabBar.isHidden = false
}
This will ensure that as soon as ChatRoomVC appears on the screen, its tabBar will be presented, too.

iOS Storyboard presenting tab bar modally vs push in XCode 8

Consider a storyboard where we have UITabBarController, in it any UIViewController(lets call it VC) embedded in a UINavigationController. We want VC to have a BarButtonItems on its navigation bar. This storyboard is presented by push segue from another storyboard (having another navigation controller).
Everything looks OK in XCode, but navigation bar does not change in VC at the runtime. However when I change presenting this storyboard from push to modal, everything seems to be fine. IMHO it is because of embedding the navigation controller but I do not see any reason why it is not working. Any idea how to fix it legally (presenting by push) and without any pain would be helpful.
Thanks in advance
So I think you will have to employ some code to fix your issue but not much. I built a test project to test this and will attach images along with code.
First if I understand you correctly you have a navigationController push the new storyboard in question. See attached image.
I named the storyboard being pushed because that is what is happening. Then in my storyboard named Push here is the setup.
In the first view controller of the tabbarcontroller I added the below code. Obviously this hides the navigation controller that pushed us here. If you then visit controller number 2 our new navigation controller and items show. If hiding the navigation controller in the tabbarcontroller view controller 1 is not what you want to do then. continue reading.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//or to unhide from returning the opposite ->self.parent?.navigationController?.isNavigationBarHidden = true
self.parent?.navigationController?.isNavigationBarHidden = true
}
If you did not want to hide the navigation controller in the first view controller but when visiting controller 2 you want to see your items then add this to your viewWillAppear and in the first controller in viewWillAppear change the code from true to false.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Do any additional setup after loading the view, typically from a nib.
self.parent?.navigationController?.isNavigationBarHidden = true
}
This hides the parent navigation controller as basically that was covering up your navigation controller in your example. So above hides the parent navigation controller. This is also why presenting modally worked. Your navigation controller was hidden from the start. Hope this helps.
**Edit
If you want the navigation controller in tab 2 view controller but you want to keep the parent in tab one to be able to go back with the back button you can set this in viewWillAppear instead so it would look like this in view controller 1.
//tabcontroller vc 1
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = false
}
And in tabcontroller view controller 2 with the item in the bar you could do this.
//tabbarcontroller vc 2 with own navigationcontroller
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.parent?.navigationController?.isNavigationBarHidden = true
}
Finally if you want the back button visible in both controllers but want different right buttons do it programmatically in viewWillAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.navigationItem.setRightBarButton(UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(FirstViewController.editSomthing)), animated: true)
}
And if you want to remove it in the other controller
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.navigationItem.rightBarButtonItem = nil;
}
In Both of the above examples directly above this, we are keeping the parent navigation controller so you would not need to embed your view controllers of the tab controller inside uinavigation controller.
You could also use a combo of the above code if you want the hide/show parent navigation controller in viewWillAppear as well. Some of this is dependent on the view hierarchy you choose now and in the future.

Navigation Bar Not Showing after Adding NavigationController

I have an existing UITableViewController that I've embedded in a NavigationController. However, the Navigation Bar is not showing when I present the view.
Presenting the TableViewController (its Storyboard id is: SelectServicesController) :
if let selectServicesController = self.storyboard?.instantiateViewControllerWithIdentifier("SelectServicesController") as? UITableViewController {
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
}
This is what it looks like when I build (nav bar does not show):
So I just did this and at fist could not get it to show up at all. Then Figured it out, You just need to select the navigation controller and set it to be the ✅is initial View Controller
This is what your storyboard should look like
Then to make everything show up I added this to my viewDidLoad of the view the Navigation controller is presenting. This step is more optional.
self.navigationController?.navigationBar.barTintColor = UIColor.redColor()
self.navigationController?.navigationBar.tintColor = UIColor.blackColor()
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.blackColor()]
navigationController?.navigationBar.hidden = false
And this is what it looks like
mmmm Red on black 🤓 Hope that helps you.
You're presenting a UITableViewController, which doesn't have a navigation controller as a parent (even though your Storyboard has it first, you're not actually using it).
You can fix this by doing something like this:
if let selectServicesController = self.storyboard?.instantiateViewControllerWithIdentifier("SelectServicesController") as? UITableViewController {
let navigationController = UINavigationController(rootViewController: selectServicesController)
self.navigationController?.presentViewController(navigationController, animated: true, completion: nil)
}
Or by setting the navigation controller as the initial view controller of the storyboard and then calling it like this:
if let selectServicesController = self.storyboard?.instantiateInitialViewController() {
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
}
I encountered the same problem. I solved it by Changing the segue to the navigation controller that embeds the View Controller I want to display.
Hopefully it would work for you.
Let me know if it is a bad practice.
let storyboard = UIStoryboard(name: "Expense", bundle: Bundle(for: PTCAddExpenseViewController.self))
let controller = storyboard.instantiateViewController(withIdentifier:"AddExpense") as! PTCAddExpenseViewController
let navigationController = UINavigationController(rootViewController: controller)
self.present(navigationController, animated: true, completion: nil)
Adding this works for me:
self.navigationController?.isNavigationBarHidden = false
You're presenting the table view controller directly, not its navigation controller. If you mark the nav controller as the initial view controller (tick the "Is initial view controller" box in the attributes inspector), then you can instantiate and show it by:
if let selectServicesNavController = self.storyboard?.instantiateInitialViewController() as? UINavigationController {
// if you're pushing it onto an existing nav controller
self.navigationController?.presentViewController(selectServicesNavController, animated: true, completion: nil)
// if not (and this is probably the case), set the nav controller as your window's rootViewController
UIApplication.sharedApplication().keyWindow.rootViewController = selectServicesNavController
}
My guess is Xcode is ignoring the fact that your table view controller is embedded in navigation controller when presenting your table view controller with the following code:
if let selectServicesController = self.storyboard?.instantiateViewControllerWithIdentifier("SelectServicesController") as? UITableViewController {
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
}
Instead, I would suggest you modify the Top Bar setting under Simulated Metrics to suit your needs or instantiate your navigation controller instead (the latter is preferred and recommended)
In your code, change this line
self.navigationController?.presentViewController(selectServicesController, animated: true, completion: nil)
to this
self.presentViewController(selectServicesController, animated: true, completion: nil)
I read in one of your comments you want to present the table view controller modally, with the navigation bar showing. We can do this using the Storyboard. From the view controller that should display this table view controller modally, Ctrl+Drag from the view controller to the Navigation Controller of the Table View Controller. Then, select Present Modally. Set an Identifier for the segue. Then, in your code for the view controller that is presenting the table view controller modally, call:
self.performSegueWithIdentifier("YourSegueIdentifier", sender: nil)
Another way to do this without having to use any code is if the modal presentation is being triggered by something like a button. Then, you can Ctrl+Drag from that button to the Navigation Controller and select Present Modally.
Or it might be this!!
I had the same problem: the navigation bar was showing on the root view in Storyboard, but when running the Simulator - there was no navigation bar at the top of the views. This solved it:
Navigation Controller > Navigation Bar > UNCHECK Translucent (it is checked by default). This did two things:
My Navigation Bar shows on all subsequent views.
The topmost subview is now at Y=0, and not Y=64.

Navigation bar not showing iOS swift

I am having multiple view controller in my application. I want to hide navigationbar in my first view controller. So I use the following code to hide the navigation bar
navigationController?.setNavigationBarHidden(navigationController?.navigationBarHidden == false, animated: true);
Now I want to add navigation bar in some other viewController but, my navigation bar not visible in that viewcontroller. Why it is happening?
My storyboard showing the navigation bar but once I try to run my application it is gone.
If I hide navigation bar from one view controller then we can't use navigation controller, Is it so? I hope I am wrong. Then what are the reasons for navigation bar not shown?
EDIT:
Also I want my view controller in portrait mode only. So I did the following Is that causing the issue?
extension UINavigationController{
public override func shouldAutorotate() -> Bool {
if (UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft ||
UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight ||
UIDevice.currentDevice().orientation == UIDeviceOrientation.Unknown) {
return false
}
else {
return true
}
}
public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return [UIInterfaceOrientationMask.Portrait ,UIInterfaceOrientationMask.PortraitUpsideDown]
}
}
Edit 1:
I am using following code to move from one view controller not link from the storyboard. Is that causing issue now?
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController = storyboard.instantiateViewControllerWithIdentifier("HomeVC")
presentViewController(secondViewController, animated: false, completion: nil)
Edit 2:
Please check my following screenshots. Which are my settings for secondview controller
Edit 3:
Here is my navigation controller attribute inspector
Navigation Controller is a controller, which has stack of view controllers. So if you have something like this:
NAV -> A -> (segue) B
Even if you'll hide navigation bar you still should be able to make segues. Also can't you just unhide navigation bar in second (B) view controller in viewWillAppear? And in first the same way hide it on viewWillAppear.
edit: Final solution to the problem:
Use:
let controller = storyboard.instantiateViewControllerWithIdentifier("HomeVC")
self.navigationController!.pushViewController(controller)
instead of:
let secondViewController = storyboard.instantiateViewControllerWithIdentifier("HomeVC")
presentViewController(secondViewController, animated: false, completion: nil)
Because pushViewController will add secondViewController to its stack. presentViewController was replacing your navigation controller that's why you couldn't see navigation bar.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Hide the navigation bar on the this view controller
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Show the navigation bar on other view controllers
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
in viewDidLoad method of the view controller in which you don't want to show navigation bar add the line
navigationController.navigationBarHidden = true
you are presently hiding in all view controllers
Edit: You are presenting view controller instead it should be
self.navigationController!.pushViewController(controller)
do like in viewcontroller based hidden using Swift 4.0
To hide navigationController in viewWillAppear
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = true
}
To unhide navigationController in viewWillDisappear
override func viewWillDisappear(animated: Bool)
{
super.viewWillDisappear(animated)
self.navigationController?.isNavigationBarHidden = false
}
I am having same requirement in my swift project.
this is how I have handled Navigation bar
Make sure your first screen is embedded into Navigation controller
example we have two screens A and B
In screen A you need to hide navigation bar in viewWillAppear
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
//hide navigation for screen A
self.navigationController?.navigationBarHidden = true
}
for enabling Navigation in screen B
you need to add below code in screen A
override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!)
{
if (segue.identifier == "screen B's segue identifier here")
{
//enable navigation for screen B
navigationController?.setNavigationBarHidden(navigationController?.navigationBarHidden == false, animated: true)
}
}
Using above style, I can enable or disable navigation bar for specific screen, whenever I want
If you need to have this navigation bar hidden only in this controller, the best way is to show it in viewWillDisappear() and hide in viewWillAppear().
It's too late to reply and there are other good answers but I would like to share what worked for me.
let controller = self.storyboard?.instantiateViewControllerWithIdentifier("HomeVC")
self.navigationController!.pushViewController(controller!, animated:true)

Resources