UISearchBar and UINavigationItem - iphone

I can't seem to get a UISearchBar to position itself from the far left to the far right in the navigation bar. In the -(void)viewDidLoad method, I have the following code:
UISearchBar *sb = [[UISearchBar alloc] initWithFrame:self.tableView.tableHeaderView.frame];
sb.delegate = self;
self.navigationItem.titleView = sb;
[sb sizeToFit];
[sb release];
When you build and run, it looks just fine at first glance. However, looking more closely, you can tell there is a margin/space on the left. This wouldn't be a big deal in the grand scheme of things, but when I tap the search bar to start a search, I animate the cancel button into view. Because the search bar is positioned slightly to the right, the animation is jerky and the cancel button falls off the end like so:
link text
It seems as if the UINavigationItem is like a table with three cells, where there is a padding on the first and last which I can't remove - nor does there seem to be a way to 'merge' it all together and then place the search bar there. I know this look is possible, because the AppStore search has a search bar in the navigation bar and it goes all the way to the edges. Anyone know how to get the search bar to go all the way to the edges so my slide-in cancel button animation will work properly?

Actually, there's a really simple solution. All you have to do is create a zero-width view for the back item:
UIView *hackView = [[UIView alloc] initWithFrame:CGRectZero];
UIBarButtonItem *hackItem = [[UIBarButtonItem alloc] initWithCustomView:hackView];
self.navigationItem.backBarButtonItem = hackItem;
[hackView release];
[hackItem release];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
[searchBar sizeToFit];
self.navigationItem.titleView = searchBar;
[searchBar release];
Be sure to do this in your loadView method, not init. I'm not sure why that makes a difference, but it does.
Apparently it's about timing. Having it in loadView stopped working for me, but putting it in viewWillAppear works (with a check so that it's only done once, of course). I think the idea is to set the titleView after some initialization has already completed.

The following code hides the navigationBar just for this UIViewController:
- (void)viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
So to get the UISearchBar to show in the UINavigationBar's place, on your root view controller just have your search bar where the navigation bar would be normally!

I think I found out the answer - though I haven't tested to verify. In the issue I provided above, I have the following structure:
tab bar controller -> navigation controller -> view controller(s)
The search bar in question was in a view controller, which in turn was in the navigation controller, which navigation controller is in the tab bar.
I was casually watching the Stanford CS 193P (Spring 2009) courses and at the end of Lecture 13, the answer may have been presented. Alan Cannistraro stated that the structure of the Presence app should have this structure:
this structure http://img143.imageshack.us/img143/6/viewcontrollerstructure.jpg
where the bottom view controller (adjacent to the tab bar controller) was the view controller which had the search bar control. He warned if it's not done in this fashion, you'll "run into problems". Possibly the problem I faced? I believe so.

Maybe apple is using an UISearchDisplayController for doing these kinda things.

Related

Navigation Controller - How to Add in Another View Controller in Xcode?

I'm relatively new to iOS programming but I'm learning bit by bit. I've got two nib files, one is my HomeViewController and the other is called 'ReceiptTableViewController'. The HomeVC should not have a top nav bar but the ReceiptTableVC should, with a title and 'back' where the user can swipe to go back to HomeVC.
How would I go about adding this? I've dragged the Navigation Controller to the side of my ReceiptTableVC in the nib file.
I've searched for various answers but some contradict each other as the authors use different versions of Xcode, and some start with storyboards, etc.
Any help is much appreciated!
I haven't used storyboard
You can use this method to decide whether your navigationBar show or not in your viewController.[self.navigationController setNavigationBarHidden: animated:];
In your AppDelegate:
UINavigationController *naviController = [[UINavigationController alloc] initWithRootViewController:homeController];
naviController.navigationBarHidden = YES; //set home controller navigation bar hidden.
self.window.rootViewController = naviController;
Then in your ReceiptTableViewController's viewDidLoad method:
[self.navigationController setNavigationBarHidden:NO animated:NO]; // show the navigation bar.
This is how to declare a UINavigationController programmatically. You can have a try.

how to add items to the UINavigationBar

I am new to iPhone development.
my application is based on UInavigationBar .
I want to add a navigation bar item in one of my xib, but in the .xib i just simulate the navigation bar so i can't drag and drop the item. thank you
You'll want to add the nav bar buttons programmatically. You see, your xib has a view that is shown within the content view of the UINavigationController. It is the UINavigationBar to which your app has access and which controls the nav bar items. As you point out, your xib has just a placeholder for the nav bar, which is really a convenience for you so your view is sized correctly as you lay it out.
In your UIViewController for the xib, you an add view-appropriate nav bar items with code something like
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]
initWithTitle:#"View" style:UIBarButtonItemStylePlain
target:self
action:#selector(viewControls:)] autorelease];
Does that make sense?
In order to be able to add items into a UINavigationBar, you need to first add a UINavigationBar to your view and then add items to it.
You cannot drag and drop items on a simulated navigation bar. A simulated Navigation Bar is just there to make sure you have a correct estimate of the view size available to you if you are adding a Navigation Bar by some other means or from code.
You should be using a UINavigationController for a navigation based hierarchy. That will take care of a lot of the lower details of how to make navigation work as you would like it to. I would also recommend setting that all up programmatically. Here is how you would do that.
// Initial setup of navigation
YourViewController *yvc = [[YourViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:yvc];
[[self view] addSubview:[nav view]];
Then when you want to go to a new view controller (the animated sliding that you normally see), you do this
// From inside 'YourViewController',
// this is normally when the user touches a table view cell
NewViewController *nvc = [[NewViewController alloc] init];
[self.navigationController pushViewController:nvc];
If you want to change the title or the buttons, you do this
// This is normally in viewDidLoad or something similar
[self.navigationItem setTitle:#"Hello World!"];
[self.navigationItem.rightBarButtonItem:/* A UIBarButtonItem */];

UINavigationController Toolbar Buttons

I have a UINavigationController that I've set as the rootViewController of my window. In the NIB file I've set it up so that it has a "Bottom Bar" of "Toolbar". In Interface Builder I've added a UIBarButtonItem. This all works great and I can handle the button click fine. When I hit one of the buttons, I push a new view onto the ViewController and that works fine too. One problem, my button disappears when the view is loaded. Now in the subsequent view I can set the bottom bar to be a Toolbar and I see it in Interface Builder, but I cannot add any buttons to it.
I know I'm either missing something obvious or thinking about this incorrectly but how do I add UIBarButtonItems to subsequent views pushed to my nav controller? I'm talking the bar at the bottom, not the nav bar at the top.
Any ideas?
The toolbarItems property on the UIViewController is what you are interested in. You can create UIBarButtonItems programmatically and add them to a new toolBarItems array in viewDidLoad.
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem* editButton = [[[UIBarButtonItem alloc] initWithTitle:#"Edit" style:UIBarButtonItemStyleBordered target:self action:#selector(editAction)] autorelease];
[self setToolbarItems:[NSArray arrayWithObject:editButton]];
}
This worked better for me:
[[self navigationItem] setLeftBarButtonItem:homeButton];
You can do the same for the right side.

Pushing a UITabBarController with a UINavigationBar onto an existing UINavigationBar

Okay I am working on a group project and what we are trying to do is create a "Results Screen" which has It's Own UINavigation and contains two TabBars in it. We are trying push that ontop of an existing UINavigation. Right now at the moment of this code. We have our main App Delegate and in it we instantiate a beginning navigation and tabbar.
startTabBarController.viewControllers=[NSArray arrayWithObjects:templatesVC,recentJobsVC,profileVC,aboutVC,nil];
startTabBarController.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"D2P_Logo2.png"]];
startTabBarController.navigationItem.titleView.backgroundColor = [UIColor clearColor];
UIBarButtonItem *tempRightBarButton = [[UIBarButtonItem alloc] initWithTitle:#"New"
style:UIBarButtonItemStylePlain
target:self
action:#selector(makeJob)];
[startTabBarController.navigationItem setRightBarButtonItem:tempRightBarButton];
[mainNavBar pushViewController:startTabBarController animated:NO];
[window addSubview:mainNavBar.view];
Now what we want to do is add another Tab Bar on top with a segmented navigation controller and a tab bar controller.
At the moment were are trying a UIViewController without a xib to do this. I've tried various methods but all that has come up is a blank screen.
In Terms of Layout of what we have we have a Navigation Controller and on it's stack is a UITabBarController -> UITableViewController -> UITableViewController and we want to add on top of that a UIViewController with a UINavigationController and UITabBarController in that.
Any Advice would greaty be appreciated. Thanks in Advance.
Never mind, I found a solution. Ended up using a ModelViewController and then had some issues with a white bar which I solved by searching around these very forums and found out that I just had to hide the status bar before showing the ModelViewController and showing it after it was loaded.
Thanks anyways though.

switch views using a button, going to a table view, iphone

My program has 4 buttons and each button calls a different table view. That works fine, but my problem is, the view controller I'm using brings up a table view that covers up my navigation bar and my tab bar. I need to replace that coding with something that will bring up a table and not cover up my nav and tab bars. Here is the coding I'm using:
-(IBAction)buttonNorthWest {
NorthWestViewController *nwController = [[NorthWestViewController alloc] initWithNibName:#"NorthWestView" bundle:nil];
self.nwViewController = nwController;
[self.view insertSubview:nwViewController.view atIndex:0];
[self presentModalViewController:nwViewController animated:YES];
[nwController release];
}
The [self presentModalViewController....] is the problem. Does anyone know how I can replace that code with something that keeps my nav and tab bars?
Thanks,
Jaime
On the iPhone, all modal view controllers must be full screen as seen here http://developer.apple.com/iphone/library/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instp/UIViewController/modalPresentationStyle
As an alternative you could display the tableview as a subview and adjust the frame so that it does not overlap the nav or toolbar.