I want to achieve something similar to Facebook's way of presenting the comments view controller for a specific post. In below picture one can see, that the pushed new view controller is presented "full screen" (for the lack of a better way of describing the behaviour). It seems to me like some kind of modal segue rather than a push one. When trying to recreate that in my own app I can't achieve that the whole navigation bar is included in the presentation segue. Only the view inside the presentation hierarchy is changed. I want the second view controller to be entirely white (the view as well as the navigation bar) but both view controllers should have the default swipe-to-go-back behaviour. How can that be done?
What they're probably doing is hiding the navigation bar.
You can achieve the same effect if you set navigationController?.navigationBar.isHidden = true (can also do it on navigation bar in UINavigationController from the storyboard), make a regular show segue and just display it using performSegue(withIdentifier: "nextScreen", sender: nil). You can then make your own UI logic for displaying back buttons etc.
Related
I need to make a custom navigation bar, since it will have search bar and some other views, it will be easier if I just make custom view instead of inserting view to navigation controller programatically
like the picture below, there are 2 ways to implement custom navigation bar view, by embedding navigation controller (yellow VCs) and use or just using present modally segue (blue VCs)
personally I will choose to use navigation controller because 'maybe' there are some methods that has already built that I can use. but the problem is, the custom navigation view (red color) in navigation controller it seems overlapped by the actual navigation bar in storyboard, I don't know how to hide the navigation bar from navigation controller in storyboard, even though if I use self.navigationController?.setNavigationBarHidden(true, animated: animated), it won't be a problem.
what is the right approach to make custom navigation bar like this?
In IB the navigation bar is shown only to simulate what it might look like when you run the app. The decision to show this is inferred, by default, by the fact that it is downstream from the navigation controller. Luckily you can change this option.
When performing a custom modal view controller transition, the view controller you're coming from sits behind the new one nicely (think of Apple's "form sheet" style presentation on an iPad for instance), and when you rotate the device the previous view controller visible in the back rotates as well.
I'm unsure how to get this functionality with a UINavigationController custom push animation. It seems it isn't expected for the previous view controller to be visible from behind and it isn't.
I could take a screenshot, but it won't update on landscape rotation.
How is it done so easily with a modal transition and how do I replicate that for navigation controller custom transitions?
As far as I understand the UINavigationController class such functionality cannot be achieved through it.
UINavigationController is a container controller, which can show only one VC within it at a time. It keeps all the VCs in the stack, but not their views (views are kept by VCs themselves).
Unlike it, the modal presentation is a special type of VC-presentation, and it's not limited by the container-functionality.
I have a simple Navigation View Hierarchy that has 2 views it goes between. I wanted a customized navigation bar, so I have the default one hidden, and I've implemented a Container View which is shared between the 2 views in the nav hierarchy.
Everything works as I want it to, except when I segue to the lower or higher view the top bar appears slides away and reappears on the new view. I would like it to appear stationary when I push or pop to other views in the hierarchy.
Is there an easy way to do this? Or should I delete my custom shared Container View and try to make this work with the Navigation Bar (which I have currently "hidden")?
I had to do this for a client once. The way we did it was, like you said, make an encompassing view controller that housed a container view. Within this container view, we embedded a UINavigationController and would manually pop and push UIViewControllers to its navigation stack. Of course you want to hide the UINavigationController's nav bar.
It sounds like you sort of implemented this, but instead you just embedded a plain old view controller inside your custom navigation controller, and then segue to another view controller that is also embedded in the custom view controller? Ideally you want one instance of this custom nav controller with an embedded UINavigationController. I believe you will have to do all the view controller transitions programmatically.
Opinion: Personally, I would recommend against doing this. I believe that an app should feel like an extension of the OS it's on. A user should feel it's a part of their phone. Using the native navigation bar also decreases the level of effort a user is required to put forth to understand your app.
I know you're thinking "but it's just a nav bar" but we're talking about the same people that will potentially uninstall an app if it takes longer than 2.5s to load.
I wanted a customized navigation bar, so I have the default one hidden
That's your mistake. The way to get a customized navigation bar in a UINavigationController interface is to initialize it with init(navigationBarClass:toolbarClass:). Now the built-in navigation controller is using your navigation bar! And from there on, all will be well.
https://developer.apple.com/reference/uikit/uinavigationcontroller/1621866-init
I have a simple table view controller which has a plus button in the navigation bar. That modally leads to a place where users can insert information into text fields. These are situated throughout the view controller.
When it comes to editing a cell from the table view, I use a "Push" segue instead of modal because that seems more natural for the user experience rather than a view controller coming up. I have created a new view controller for the "editing" with the same text fields in the same location.
When I use the push segue, all of the text fields are a long way below where they should be. I've checked the x,y position and it's exactly the same as the modal view to add.
When I use Modal, then everything is exactly where it should be.
My table view is embedded inside a navigation controller so I thought when I push to another view, it would just accept that in the navigation controller.
Please could anyone shed some light on this as to why with a push segue, I'm getting messed up views, and how to fix this?
Thanks!
When doing the push is your controller using the whole height of the screen or not?
Could be the navigation bar and status bar are causing them to be out of place where as in the modal you would only have the status bar if not hidden
I am a newbie to IOS programming and currently i have a tab bar application with two tabs. I have two questions.
The first tab shows a map, imagine it with some pushpins. There is a button on the navigation bar and when this is clicked i want the map view to to move out and a list view to come in. You can see the UI from the image. The button is called list.
Now when i click list I want this view to go away and the list view to come in. So here are my questions ?
1) How do i do this ? I tried the navigation model but i don't want that because I do not want a back button. I tried to make two different views and just dragged the button to that view but the app crashes. I just want the list button on the nab bar and when clicked the view changes to the list view and the button text changes to map. So now if I click the button again it should go back to the map view and the button changes to list.
2) How do i achieve the animations for this ? Ive seen some app where the page flips around and I've seen some options like reducing the opacity etc but I want to achieve the flip animation.
Thank You for any help I get. I really appreciate it.
Interface Builder can do most of this. Hold down the control key and drag from your map View Controller's UIBarButtonItem titled "List" to your list View Controller, then choose the Action Segue "modal". An arrow appears representing the segue; click on it and use the Attributes Inspector to change the Transition to "Flip Horizontal". Here's a video
Or, you could do this programmatically with presentViewController:animated:completion.
Now to get back to the map from the list, I believe that must be done programatically. Create a method that calls dismissViewControllerAnimated:completion: and make your list View Controller's UIBarButtonItem titled "Map" trigger it.
After reading your comments, I am wondering... if the structure of your app is logically a tabbed app structure (as indeed you refer to it as a 'tab bar application'), shouldn't you consider using the UITabViewController instead of a NavigationController? That is what it is designed to do, after all.
If you do use a TabViewController you should reconsider your desire for flip animation, as that doesn't really make UI-sense for tabs. If you can dispense with the flip animation, TabViewController could be a good way to go and you should at least experiment with that before dismissing the idea. It is also designed to grow... you can incorporate any number of tabs in a tab bar. Check out the apple docs (with pictures!)
You will notice that tabs are at the foot of the screen, whereas your 'tab' navController buttons are in a navbar at the top of the screen. This also helps as your app grows, as it is straightforward - from a UI design point of view and programmatically - to incorporate navControllers as navigation tools within individual tabs. For example, if your map/list flip routine does indeed make sense for this part of you app, you can keep this as a single tab (in it's own navigationController) and add other tabs for other parts of the app...
update
From your comment, you are saying that you are interested in the navController-inside-tabBarController setup. In this case here are some ways to get flip transitions AND no back button..
(1) modal presentation
The easiest way to get what you want is to set up one of your viewControllers (say the map view) to present the other one (the list view) modally.
If in the storyboard:
embed your mapViewController in a navController with a navbar button for navigation to the listView as in your picture
add your listViewController to the storyboard and embed it in it's own navContoller (not the mapViewController's navController). Drag a barButtonItem to this navController and wire it up to an IBAction in listViewController
CTRL-drag from mapViewController's 'list' button to the listViewController to create a segue. Select the segue and in the attributes inspector set the segue type to 'modal', with transition 'flips horizontal' and 'animated' checked. Give it a name in case you want to refer to it in code.
in the listViewController's IBAction add this:
[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
That should achieve your result. You can use the completion block to send information back from the list view to the map view, and/or set the map view as the listView's delegate.
If you are not using the storyboard check this apple guide
Presenting View Controllers from Other View Controllers
especially "Presenting a View Controller and Choosing a Transition Style".
There is one catch with this approach - when the presented view flips onto the screen, the entire previous view, including the tab bar, is flipped out of the way. The idea is that this is a modal view which the user is required to dismiss before doing anything else in the app.
(2) push/pop in a single navController If this does not suit your intent, you can navigate using a single NavigationController with push and popping of views, and you can hide the back button ... but you really would need to keep the back button functionality as you do want to go back to the mapView, not on to a new map view.
To hide the back button try:
self.navigationItem.hidesBackButton = YES
in the uppermost viewControllers' viewDidLoad
Then you can add a barButtonItem in the xib/storyboard, with this kind of IBAction:
[self popViewControllerAnimated:NO]
or
[self popToRootViewControllerAnimated:NO]
You would have to construct the flip animation in code as it is not supported as a built-in with UINavigationController (best left as an exercise for the reader!)
(3) swapping views in a single viewController As ghettopia has suggested, you could use a single viewController inside a navController (or with a manually place navBar) and swap two views around using the UIView class methods
transitionFromView:toView:duration:options:animations:completion
transitionWithView:duration:options:animations:completion.
This could be a good simplifying solution as your list and map are essentially two views of the same data model.