How can I make one Tab Bar button refer to two views/controllers in iOS - ios

I'm developing an iOS app just now with a Tab Bar navigation.
I have two screens which show the same information but in different formats (say, list and grid).
The two screens are different enough that they require separate controllers.
Users can toggle between the two views from a shared control bar button (toggle) at the top.
Scenario:
User presses the 'Places' button for the first time and it shows the places as a list.
They press 'grid' to see the same places displayed as a grid.
The user presses another tab bar button to navigate to a different screen.
When they press the "Places" button again, the app remembers their last viewed screen for places was the grid so the grid view is shown.
The user may then toggle back to list view. etc...
Can anybody recommend the best approach to achieving this?

One approach is to use one view controller that manages both views. That way, you don't have to bother with synchronizing data or subverting the normal function of UITabBarController -- there's just one controller. Also, don't try to overload the meaning of the tab for that controller. Instead, add a button to both views that tells the controller to switch to the other view. That'll be easier for your to build, and (more importantly) easier for the user to understand. It's not nice to make familiar controls do unfamiliar tricks.
If your view controllers are such that combining them into one would be complicated, then you can use two controllers and simply swap them in and out of the tab bar by modifying the tab bar controller's viewControllers array. You can still avoid having to sync data between them by having both controllers refer to the same data model.

I was trying to achieve this same thing, and it can actually be done with a basic setup of a TabBarController, NavigationControllers, ViewControllers, push segues, and unwinds.
TabBarController
|==> NavigationController --> PlacesController(grid view) --(push segue from nav bar)--> PlacesController(list view)
|==> NavigationController --> OtherController
|...
Make sure to have an unwind segue back from the list view controller to the grid view controller.
If you toggle between views then go to another tab (e.g. otherController) and come back, you'll return to the last view you were seeing because that's what is at the top of the stack of the NavigationController.

Related

Custom/common toolbar in Swift

I'm quite new to Swift and am working on an app where I'm not sure how to setup the navigation. It works with a tab bar, except that I want the bar to display nomatter what view is being displayed. There are 4 "main" views that the user should always be able to get to. The problem comes when I get into subviews of one of those main views.
I have the tab bar with the 4 icons for the primary views. It's currently displaying the "activity list". When the user clicks on an activity, it will display a list at the next level of detail. However, that view is not one of the primary ones that is represented in the tab bar, so it has no tab bar and no way to transition directly to one of the primary views. You have to back your way out to the Activity list before you can select a different tab.
Say that the main views (represented in the tab bar) are A, B, C, and D. I want to be able to display the same toolbar on all sub-views (e.g. C-1, C-2, etc.) and allow direct transition to any of the other main views, without the user having to manually back out of each sub-view.
What is the "best" way to accomplish this?
1) Should I be creating a custom toolbar object that gets implemented on every view controller?
2) Should it be a combination of tab bar and tool bars?
3) If I have drilled into a stack of views, do I need to pop all of those views individually before I can switch to a different tab?
4) What do I use as my "root" view?
Thanks for any suggestions. I have hunted, but haven't found an example of a scenario quite like this.
I think I figured it out. I needed to embed each "tab" view in a navigation controller.
So...
Tab Bar Controller --> Navigation Controller --> View Controller --> "view stack"
The tab bar now remains at the bottom for every view, and if I touch the tab icon a second time, it goes back to the original tab view controller.

What approach should i use when making tab bar application

I'm started to work at new place as iOS programmer. I joined existing project and got an assignment that i don't really know how to approach.
So my problem is this: when you press a button, next window has to have a tab bar with four icons, this means four different navigation stacks. Its not that hard to make, but in main screen i have more then four icons, and if i press any one of them next window always has to have a tab bar with four static icons, like shortcuts or something.
So what should I do? Does anyone had the same situation? I want to start with a good advice to save trouble later on.
You should probably rethink the app design. Tapping an item on the tab bar shouldn't result in a different number of tab bar items, as it leads to an unstable and unpredictable UI.
While not the most efficient in terms of visible content, you could introduce a segmented control (or a similar custom view) on top right under the navigation bar (if there is one), as seen in the Facebook app (though here it is used to perform actions, not changing views).
Your root view controller should be embedded in a navigation controller. Then push a view controller which contains any number of tab bar items not TabBarController. Then you can present each view controller either push or custom.

What navigation strategy to choose for iOS project?

I have 4 screens in a project. I know two ways to move from one view to other:
UINavigationController
One UIViewController and add subviews to that UIViewController.
But, In all screens bottom bar is same. Bottom bar is having some buttons.
So, In my point of view, adding subView to one UIViewController is better way.
But I don't know which is best method and standard way for developers?
The answer depends entirely on the way that you expect the users to navigate from one screen to the other:
If end-users should be able to get from any screen to any other screen, use tab bar controller - UITabBarController will hold the other four views, and present a tab bar at the bottom. If you do not want the tab bar, you can hide it.
If end-users on each view have two choices of view controllers to go to, next and prior, use a page view controller - This is more appropriate in situations when the navigation is limited to next/previous page.
If end-users need to be able to go back to the previous screen, use navigation controller - UINavigationController keeps track of the views that you visited, and provides navigation to go back.

Swap/ Transitioning between views iOS programming

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.

"Slide" segue between UITabBar views

My iOS 5 app uses storyboarding with a UITabBarController. There are three "tabs" each displaying a view controller which has been linked using a relationship back to the UITabBarController. At the moment each view controller appears when you tap the relevant tab, as expected. However, for a more gracious transition I would like to slide the view controllers on and off screen.
By way of example, if I am currently on Tab 0 and then select Tab 1 the view controller on screen (for Tab 0) should slide off to the left-hand side of the screen, and the new view controller (for Tab 1) should slide on from the right-hand side of the screen.
I have been able to achieve this behaviour using a custom UIView as the tab bar but would like to know whether this is possible with a custom segue in storyboarding, as that would certainly save a lot of coding (and also would keep things a fair bit neater in the project)?
Thanks in advance for any assistance.
I am trying to do the same thing.
Unfortunately I think the relationship segue does not allow any customization as it just connect tab bar and the tab bar items together, and not a transition.
My guess is we have to do the transition ourselves when the view appeared.

Resources