I was able to create an app using Storyboard - it has a navigation controller containing a table view controller with a search display controller and worked as expected.
I then decided to customize it by adding a UIButtonBarSystemItemSearch (magnifying glass) to the navigator bar so that when touched it would display the search bar over the navigator bar, just like setDisplaysSearchBarInNavigationBar does. To do this I removed the UISearchDisplayController from the storyboard and added it programmatically as shown in the code below. The btnSearchClicked function is called when the magnifying glass is touched, so the button is hooked up right.
My project is very similar to the Apple example project "AdvancedTableSearch" but without the scope bar.
- (IBAction) btnSearchClicked:(id)sender
{
//Set up search bar
UISearchBar *mySearchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)];
[mySearchBar setDelegate:self];
[mySearchBar setShowsCancelButton:YES animated:NO];
// Set up search display controller
UISearchDisplayController *mySearchController = [[UISearchDisplayController alloc] initWithSearchBar:mySearchBar contentsController:self];
mySearchController.delegate = self;
mySearchController.searchResultsDataSource = self;
mySearchController.searchResultsDelegate = self;
//mySearchController.displaysSearchBarInNavigationBar = YES;
mySearchController.navigationItem.titleView.opaque = NO;
[self.navigationController.navigationBar addSubview:self.searchDisplayController.searchBar];
}
I am having two problems with this approach. The most important one is that even though I set the delegate properties, when I type into the search bar none of my delegate functions are called (specifically shouldReloadTableForSearchString).
The second problem is that the cancel button doesn't display despite calling the setShowsCancelButton method.
I've been learning iOS for the last year and reading everything I can find on SO, but can't figure this one out. This is my last resort and I will fall back to the old storyboard approach with standard search bar if I must. The reason I like this other approach is that I have a very long list of contacts (~5000) and don't want to have to scroll to the top to get the search bar.
Looks like you're not adding the right searchDisplayController? you added self.searchDisplayController but inited a mySearchController. Try putting the last line as:
[self.navigationController.navigationBar addSubview:mySearchController.searchBar];
Related
ran into a weird issue. If I set the prompt on the navigation controller, navbar overlaps the content of the screen. What is the proper way of dealing with this?
-(id)initwithsomestuff:(stuff)
{
...
self.title = #"My Title";
self.navigationItem.prompt = "#Prompt";
...
}
When this view controller is pushed on, it first appears, then it resizes it's navigation bar to show the prompt in it. But that has a nasty side effect of not resizing the screen content below and covers a good amount of stuff I actually need on the screen.
What's a preferred way of handling this issue? Layout is in xib if that helps.
One problem you have is your init function needs to call super. Following your example, it would look like this:
- (id)initWithSomeStuff:(id)stuff
{
self = [super init];
if (self) {
self.title = #"My Title";
self.prompt = #"Prompt";
}
return self;
}
Next, are you developing against iOS 7? It is intended behavior to cover the content with the navigation bar by default. If you want to suppress this behavior, perform the following on your view controller:
self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = NO;
You can also set these on the View Controller in the Story board. They are shown on the Properties tab, under Extend Edges.
I'm adding a series of buttons to a UINavigationBar using:
NSArray *items;
items = [NSArray arrayWithObjects:
fixedSpace,
refreshStopBarButtonItem,
flexibleSpace,
self.backBarButtonItem,
flexibleSpace,
self.forwardBarButtonItem,
flexibleSpace,
self.actionBarButtonItem,
fixedSpace,
nil];
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, toolbarWidth, 44.0f)];
toolbar.items = items;
toolbar.tintColor = [[UIColor whiteColor] colorWithAlphaComponent:1.0];
toolbar.autoresizingMask = UIViewAutoresizingFlexibleHeight;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:toolbar];
All working well.
However when I rotate to landscape mode the toolbar within the uinavigationbar doesn't rotate.
Adding this code (found on SO) causes the toolbar to resize but not the buttons within it, so they are partially cropped at the bottom and no longer lines up with the toolbar background
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
CGRect navigationToolbarFrame = self.navigationController.navigationBar.frame;
CGRect customToolbarFrame = CGRectOffset(navigationToolbarFrame, 0.0, navigationToolbarFrame.size.height);
[UIView animateWithDuration:duration animations:^{
//self.toolbar.frame = customToolbarFrame;
// FAILS!!!
//self.navigationItem.rightBarButtonItem.toolbar.frame = customToolbarFrame;
// FAILS!!!
}];
}
What is the correct way to address the toolbar within the uinavigationbar?
Something like...
self.toolbar.frame = customToolbarFrame;
Or do I have to specify a autoresizemask for the UIBarButtonItems?...
self.backBarButtonItem.autoresizingMask = UIViewAutoresizingFlexibleHeight;
... trying to do so like this fails
Very curious because this code rotates toolbar fine when I include it in my code. No problem rotating the toolbar.
I assume your view controller is responding to shouldAutorotateToInterfaceOrientation? Could you include screen snapshot of what you're seeing?
Are you doing any UIToolbar category/subclass to eliminate its border? (I just subclass with empty (void)drawRect:(CGRect)rect to get rid of border, but I tried both that and the standard UIToolbar and both rotated fine.) Anyway, if you're doing subclass/category of UIToolbar, please include that code?
Also, you could alternatively just use iOS 5's rightBarButtonItems and bypass the toolbar altogether, e.g. self.navigationItem.rightBarButtonItems = items; will then add the array of UIBarButtonItem objects to the navigation bar.
This is a bit of a long shot, but how is your view controller being loaded? Some people try bypassing presentViewControllerAnimated and/or pushViewController and instead simply create a view controller, grab its view, add it as a subview of the previous view controller's view. Unfortunately, this ends up with a disconnect between the view controller hierarchy and the view hierarchy, and according to WWDC 2011 session 102 on view controller containment, this can prevent rotation events from being transmitted correctly. Make sure you're using presentViewControllerAnimated or pushViewController if this isn't your root view controller.
I don't do any of that willAnimateRotationToInterfaceOrientation or subsequent code, just the simple UIToolbar and it works fine during rotation, so I wonder if the problem rests elsewhere.
I have created a tab based application for iphone. when the 1st tab presses a first view will present. this view contains a button, on pressing it another view loads.
Code is:
-(IBAction)buttonPressed: (id) sender
{
Cities *cv=[[Cities alloc] initWithNibName:#"Cities" bundle:nil];
cv.modalTransitionStyle=UIModalTransitionStyleCoverVertical;
[self presentModalViewController:cv animated:YES];
[cv release];
}
Now problem is that this view is loading in whole screen so that I am not able to access tab bar.
I have set the frame for this view and the view is loading in this frame,
-(void)viewWillAppear:(BOOL)animated
{
self.view.frame = CGRectMake(0, 0, self.view.frame.size.width, 400);
}
but in remaining part white screen is appearing means tab bar is not accessible.
I want that whatever will be load at any time tab bar should be always accessible.
Please help me out.
Add
cv.modalPresentationStyle = UIModalPresentationCurrentContext;
Have you tried using UINavigationController inside your tabbar to dig inside your UIViewControllers??
for Ref : Adding NavigationController to Tabbar
do you really need a viewController Class for what you are trying to display??
if der's no core functionality being used, i think it will be much easier with UIView.
Happy Coding :)
I've seen this question asked around before, and found an answer for how to do this in a simple view. But... when I go to a subsequent view pushed onto the view stack, manually setting the titleView doesn't work out. The titleView view gets pushed off to the right while the back button and its text take over the left half of the UI.
Is there a standard way to do this? I've noticed the Gowalla app apparently does it quite well. I've tried a multitude of approaches including categories, subclasses, etc and haven't had any luck.
Every UIViewController has it's own navigationItem, which (potentially) has a titleView. When you push and pop view controllers in a navigation control, the parts of the navigationItem are what you are seeing. If you wanted a custom title color, you could very easily do something like the following in each of your view controllers.
- (UINavigationItem *)navigationItem
{
UINavigationItem *navigationItem = [super navigationItem];
UILabel *customLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320.0f, 44.0f)];
customLabel.text = #"My Title";
customLabel.textColor = [UIColor purpleColor];
navigationItem.titleView = customLabel;
[customLabel release];
return navigationItem;
}
The iPhone SDK 3.0 has this handy new class "UISearchDisplayController" which makes it easy to create a search bar, handling all the user input and displaying the search results.
I am using it for my new app, but there is one thing i would like to change:
As a default, the search bar should be put at the top of the UITableView that displays the search results. So when scrolling down the result list, the search bar disappears.
What I would like to achieve is having the search bar always on top and when scrolling the TableView, the search bar should stay where it is. (Reason for this: in my app there are sometimes a lot of search results, so sometimes the user has to scroll down a while, and when he realizes that he has to change his search string, i don't want to force him to scroll all the way back)
What i already did is adding the search bar to the view of the UINavigationController which is the "parent view" of my table view, instead of adding it to the table view directly:
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
searchBar = [[UISearchBar alloc] init];
searchBar.delegate = self;
[searchBar sizeToFit];
CGFloat searchBarHeight = [searchBar frame].size.height;
CGRect mainViewBounds = delegate.navController.view.bounds;
[searchBar setFrame:CGRectMake(CGRectGetMinX(mainViewBounds),
CGRectGetMinY(mainViewBounds) + 20,
CGRectGetWidth(mainViewBounds),
searchBarHeight)];
searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[delegate.navController.view addSubview: searchBar];
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar: searchBar contentsController: self];
searchDisplayController.searchResultsDataSource = self;
searchDisplayController.searchResultsDelegate = self;
... but here my problem is, that the table view stays behind the search bar, and there is always the first TableViewCell of the search results, that is hidden behind my search bar.
Is there a way to resize the UITableView of my UITableViewController permanently, so that it starts right under the search bar?
And there's another problem: Everytime i touch the search bar, the UISearchDisplayController automatically hides the Navigation Bar and resizes the UITableView (it expands to the top), so i think that at this point the UISearchDisplayController will have a big problem with my custom sized TableView...
Thanks a lot for any help!!
I don't have a solution off the top of my head - but I will say the concern you have seems to minimized by the ability for the user to simply tap the top of the screen and have the table zoom to the top (to change search terms if it's wrong).
My general solution for having bits on the page that I don't want to scroll, is to have the UITableView inside another view. That outer view contains two things -- a bar at the top, and a slightly-shorter-than-full-page table below it.
#interface:
UISearchDisplayController < UISearchBarDelegate > *searchDisplayController;
#implementation:
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar: searchBar contentsController: self];
searchDisplayController.delegate = self;
searchBar.delegate = searchDisplayController;
searchDisplayController.searchResultsDataSource = self;
searchDisplayController.searchResultsDelegate = self;
Put this code in your TableViewController:
self.tableView.frame = CGRectMake(0,searchDisplayController?.searchBar.bounds.size.height,320,480);