I have a view controller, but when I hide the tab bar, there is just a black space where the tab bar was. I want to have my view controller sit behind the tab bar, so when I hide it, it shows the view content. I am using a simple UITabBarController. Thanks.
You can't do this, as far as I'm aware. The problem is that the view controllers sit within the tab bar controller, not the other way around.
The way to get around this would be to change the window view for a new navigation controller without a tab bar controller, or use a modal view to show content without a tab bar controller.
The problem is that your view on your view controller isn't tall enough to accommodate the space that your tab bar occupied.
CGRect current = [[self view] frame];
CGRect tabBarFrame = [[self tabBar] frame];
CGRect newFrame = CGRectMake(current.origin.x, current.origin.y, current.size.width, current.size.height + tabBarFrame.size.height);
[[self view] setFrame:newFrame];
Something like that is probably what you want. Or you can resize it in IB.
But, I don't know why you would use a UITabBarController and then hide the tab bar... If you can't see the tab bar, you cant switch tabs... thus making the UITabBarController pretty much just a UIViewController.
I believe that if you give the view property of your UIViewController a fixed bottom margin and a flexible height then it will stretch to fill the height of containing view automatically.
mycontroller.view.autoresizingMask = UIViewAutoresizingFlexibleHeight
Related
The application has a Tabbar Controller as its rootViewController. Now the requirement is on click of a button in the navigation bar, another view should come half way into the screen without any tab bar, and the other half should have the original view that has the tab bar in it. Is this possible to create?
Any help would be appreciated.
EDIT 1:
I did try
[UIApplication sharedApplication].keyWindow.rootViewController.view.frame = CGRectMake();
but the problem is, another view wont be seen in this, as the whole window frame is being shifted.
EDIT 2:
I have added a dummy pic of the requirement.
Create a custom view by subclassing UIView and show that in your current view controller in the first half.
You can use UIKit animation for animating the view if needed.
Finally found the solution to it.
On click of the button,
objThird.view.frame = CGRectMake(120, 0, 320, 480);
UIView *windowVIew = [self.tabBarController.view superview];
[windowVIew addSubview:objThird.view];
self.tabBarController.view.frame = CGRectMake(-200, 0, 320, 480);
objThird = Object of new view that i want when the button is pressed.
self.tabBarController.view superview = Gives you the window view. thus now you can add your view to the window.
And the rest is just playing with the frames of the views.
I have an application where I'm trying to duplicate what I see the Apple Store app doing, where the first view doesn't have a navigation bar, but subsequent views do.
I've tried various combinations of setting navigationBarHidden to YES and NO to manage when it's visible, but the key problem seems to be that during the transition, it's either visible or it isn't, whereas in the Apple Store app, the navigation bar is not there in the main view, but slides in from the right with the child view.
What I'm looking for is a way to have the navigation bar slide in with the child view, not appear (animated or not) before or after the transition.
Turns out I just hadn't hit on the right places to hide and show the navigation bar.
I used the answer from how to hide navigationbar when i push from navigation controller? and it works great for me now.
in your main view, initialize the childViewController. Then set the nav bar on the childViewController, the push the view controller.
ChildVC *childVC = [[ChildVC alloc] initWithNibName:#"ChildVC" bundle:nil];
[self setChildVC:childVC];
childVC.navigationController.navigationBarHidden = NO;
[self.navigationController pushViewController:childVC animated:YES];
If you are talking about what they do on the first Tab "Featured", where if you tap one of the items in the list with a disclosure indicator. It appears to slides in another view from right to left. I think they are using an animation to swap two view controllers. The one that slides in IS a Navigation controller which is why NavBar appears to slide in from the right.
You would do something like this to get that effect:
// First set up a view controller with frame set off to the right of the screen.
// Then animate it sliding to the left by setting its frame x = 0;
frame.origin.x = 0;
[UIView animateWithDuration:.4 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut
animations:^{
vc.view.frame = frame;
}
completion:nil];
I'm programmatically creating a UITableViewController class that shows a table view with a simple navigation bar (though without a UINavigationController, as there are no further levels to the table view hierarchy).
Here is the relevant code:
- (void)viewWillAppear:(BOOL)animated {
UINavigationBar *navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 44.0f)];
[self.tableView addSubview:navBar];
}
However, the navigation bar covers most of the first table view cell, and scrolls with the whole view.
How can I fixate the navigation bar above the table view, and keep it from scrolling through code?
The problem is that you are using UITableViewController. Switch to a standard UIViewController, add the tableview delegate and datasource methods, point the tableview to those methods, and then you do what you want to do. You could also add a UIToolbar in the XIB and create it that way if you wish.
If you really want a navigation bar, then use an NSNavigationView controller.
When you use a navigation controller, it takes care of this for you, but the navigation bar is just another subview. The remedy is to frame your table view relative to the navigation bar.
self.tableView.frame = CGRectMake(0,myNavBar.frame.size.height, 320, self.view.frame.size.height-myNavBar.frame.size.height);
Set the navigation bar's translucent property to NO:
self.navigationController.navigationBar.translucent = NO;
Having a hierarchy of data doesn't really drive whether or not you need to use a UINavigationController. There are three good reasons to go ahead and just use the UINavigationController.
You get the Navigation Bar for free, and the Nav Controller handles setting the proper frame of your root view controller when you set the nav controller's root view controller property to your view controller
If you one day wake up and say, "Hey! I want to add another layer of information to my awesome app!", you don't need to make any changes to the overall design (or, at most, minimal ones).
As my comment to #danh's suggestion implies, you're immune to whatever whacky changes Apple may decide to do with regards to nav bar height.
The solution to this behavior would be to add the UINavigationBar to the Parent View Controller's view:
[self.parentViewController.view addSubview:myNavBar];
I'm new in iPhone development and want to ask about the navigation controller. How can I make the navigation controller fixed over the whole application, like the facebook navigation bar. It always shows the notification, friends and messages in the navigation bar.
I'm trying to put custom view in the titleView but it disappears every time the navigation push new view?
There was a similar question posted here (https://stackoverflow.com/questions/16773312/facebook-like-navigationbar), unfortunately it was closed quite quickly. I'm redeeming its intended glory here.
You can achieve a persistent navigation bar with ease, if you think of navigation in terms of a Tab based application (with hidden tabs).
Using Storyboards:
Create a new UINavigationController (Nav 1).
Set a UITabController as the root view controller of Nav 1. (Tab Bar) Note that it will have it's own navigation bar (I've labeled it "Persistent Nav Bar").
Create another UINavigationController (Nav 2).
Set your view controller of choice (My View Controller) as the root view controller of Nav 2.
Set Nav 2 as the first (tab) view controller of the Tab Bar controller.
For Nav 1: under Attributes Inspector -> Navigation Controller -> Bar visibility, make sure that the box is ticked (so that it Shows Navigation Bar).
For Nav 2: under Attributes Inspector -> Navigation Controller ->
Bar visibility, make sure that the box is un-ticked (so that it
won't show its Navigation Bar).
If you run the app, you should see the title of the tab bar visible, and the title of your view controller hidden. This gives you the basics of a persistent nav bar. You can keep PUSHing views onto the stack from My View Controller and it will remain persistent. Presenting a MODAL view will bring up a new context, so the persistence is lost. If you repeat these steps, you should be able to create the same effect for modally presented views as well.
The remainder of this answer deals with hiding the tab bar and managing the navigation bar elements.
So that's great, but how do you place your custom view in the nav bar, and how do you hide that tab bar?
Create a subclass of UITabBarController, and assign it to the Tab Bar controller in our storyboard.
Hiding the tab bar
You can hide the tab bar in all sorts of ways. If you're interested, here's more about that (How to hide uitabbarcontroller); this little snippet is adapted from my answer in that thread:
CGRect screenRect = [[UIScreen mainScreen] bounds];
float fHeight = screenRect.size.height;
if( UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
{
fHeight = screenRect.size.width;
}
for(UIView *view in self.view.subviews){
if([view isKindOfClass:[UITabBar class]]){
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}else{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
}
}
This will shift the Tab Bar out of view and resize the view to fill up the space (without animation, as if it was never there). Add this snippet to the beginning of viewDidLoad to get that bar out of the way.
Custom view in nav bar
In the viewDidLoad method of our TB subclass, you can create your custom view with buttons and add it to the navigation bar like so: [self.navigationItem setTitleView:myCustomTitleView]; Easy.
If it doesn't show up properly, make sure you define its frame before you set it as the titleView. Then after adding it, use [myCustomTitleView sizeToFit] to get it sitting snug in the Navigation Bar.
Setting the bar button items
Setting the left and right bar button items requires a small change in notation. Normally, you would set the left bar button by referencing self.navigationItem.leftBarButtonItem. This reference is actually pointing to the left bar button of the HIDDEN navigation bar. To access the VISIBLE navigation bar, use self.tabBarController.navigationItem.leftBarButtonItem. Easy!
Handling the lost bar back button item
One thing that you sacrifice with a persistent nav bar is the management of pushed views. Things like the back arrow won't show (they are appearing on the hidden navigation bar). You can overcome this by setting your TabBarController subclass as a delegate for its view controllers (which should all be UINavigationControllers).
for (UINavigationController *navController in self.viewControllers) {
navController.delegate = self;
}
Whenever any of these UINavigationControllers push another view, you can intercept this action with this delegate method:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
In here, you can check how many view controllers are pushed:
if(navigationController.viewControllers.count > 1){
//create a custom back button here and add it to the nav bar
}else{
//set the left bar button (where the custom back button would sit) to nil
}
The custom back button can call a method in your tab bar controller subclass, which tells the currently selected view controller to pop its current view.
Is this how Facebook did it?
I can't verify that this is the way Facebook has done it (probably not), but it will achieve a similar effect. I've used it effectively in my latest app (http://www.waterboyapp.com), which was happily accepted by Apple without a hitch. I wish someone had posted this online before, hence my contribution here to save hours/days of searching.
Aside
The added bonus to this implementation (other than it's simplicity and elegance) is that you can link in multiple view controllers to the tab bar. With a for loop and a bit of creativity, you can recreate custom buttons in the navigation bar (based on the tabs) that perform the same function as the tab bar. This saves screen space (because tab bars are pretty big) and still uses the tab bar to perform your view swapping.
What yo should understand is that the UINavigationBar displayed is a property of the view controller on the top of navigation controller hierarchy. As you understand that, you can try to customize the titleView of every view controller's UINavigationBar, e.g. at viewWillAppear. You can access the navigation bar with
self.navigationController.navigationBar
where self is a loaded view controller reference.
And for the case you want to have a persistent view somewhere on the screen one of the solutions is the following: declare a property at app-delegate class, add the view directly to the window after the root view just like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// something here ...
// root view controller
[window addSubview:myRootViewController.view];
// toolbar
MyToolbar * tb = [MyToolbar new];
tb.barStyle = UIBarStyleDefault;
[tb sizeToFit];
tb.frame = CGRectMake(0, 0, 320, 70);
[window addSubview:tb];
self.globalToolBar = tb;
[tb release];
Then you are able to update the toolbar (in this case, it might be any view in general) from any view in this way:
[[[[UIApplication sharedApplication] delegate] globalToolBar] updateRightButtonItem]
So you'll need to subclass UIToolBar with MyToolbar, add some UI methods like updateRightButtonItem there, you'll probably also need to create a delegate or to handle the notifications from the toolbar catching the events on the top view controller.
This way the view of the view controllers will be animated with the navigation controller logic, but the toolbar is a window subview and isn't changed by navigation actions automatically.
this is what worked for me:
toolBar = [[UIView alloc]initWithFrame:CGRectMake(105, 20, 105, 44)];
notificationsBtn = [UIButton buttonWithType:UIButtonTypeCustom];
messagesBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[notificationsBtn setImage:[UIImage imageNamed:#"notifications-icon.png"] forState:UIControlStateNormal];
[notificationsBtn setFrame:CGRectMake(35, 0, 35 , 44)];
[notificationsBtn addTarget:self action:#selector(showNotifications:) forControlEvents:UIControlEventTouchUpInside];
[messagesBtn setImage:[UIImage imageNamed:#"messages-icon.png"] forState:UIControlStateNormal];
[messagesBtn setFrame:CGRectMake(70, 0, 35 , 44)];
[messagesBtn addTarget:self action:#selector(showMessages:) forControlEvents:UIControlEventTouchUpInside];
[toolBar addSubview:notificationsBtn];
[toolBar addSubview:messagesBtn];
[_window.rootViewController.view addSubview:toolBar];
In my iPad application i need to implement a navigation controller behavior to the right half of the screen( I can't use split view controller because i need more space in left-side - around 600px). Is there any way to create a NavigationController with a fixed frame size ?
thanks in Advance.
You should simply:
create navigation controller;
set navigationController.view.frame to necessary frame;
add navigationController.view as you main view's or window's subview.
Somsing like this:
navigationController.view.frame = necessaryFrame;
[viewController addSubview:navigationController.view];