UISearchBar animation issue - uitableview

I have a UIViewController in which I want to show a tableview with the serchBar.
//viewDidLoad
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0,
0,
SCREEN_WIDTH(),
SCREEN_HEIGHT())
style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
[self.view addSubview:_tableView];
// adding uisearch bar
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
_tableView.tableHeaderView = searchBar;
//
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
The issue happens when I click inside the uisearch bar so that the animation starts and it looks like it has a 20px unwanted offset.

In your Storyboard, select the problematic controller, look at the Attributes tab and try to edit these settings:
Under Top Bars
Under Opaque Bars
I've solved a similar problem by unflagging these settings.

I found what is causing this issue. Seems that the animation gets messed up when you set navigationBar.translucent to NO. If you make your navigationBar translucent, everything should work fine, but this is definitely not an ideal solution. I'm going to try and find a workaround.

UITableView *_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0,
64,
self.view.frame.size.width,
self.view.frame.size.height)
style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
[self.view addSubview:_tableView];
// adding uisearch bar
UISearchBar* searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
_tableView.tableHeaderView = searchBar;
//
UISearchDisplayController* searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
and I just embade my controller with UINavigationcontroller and its working quite well..

You can cancel animation by subclassing UISearchDisplayController and adding this:
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
if(self.active == visible) return;
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
if (visible) {
[self.searchBar becomeFirstResponder];
} else {
[self.searchBar resignFirstResponder];
}
}

codyko gave me an idea. It was the because the navigation bar was no translucent. So I set it to translucent on this view controller and rest when I left with the following code:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.navigationController.navigationBar.translucent = NO;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBar.translucent = YES;
}
Now that left the navigation bar on this controller slightly faded, so I added a UIView the same color as my navbar just behind it to make it look opaque. I know it isn't perfect but it works nicely.

As a reminder for anyone with similar issues. I needed to add this line that fixed things:
self.edgesForExtendedLayout = UIRectEdgeNone;

Why are you creating the searchBar programmatically instead of in the StoryBoard ?
I'm currently using searchBar, added in storyboard and it's work fine ( I have to change the contentOffset )

I have applied your code,, It works fine for me,, Just hide you navigation bar and start the search bar from y = 20, instead of y = 0;

Related

How to add and remove searchBar from navigationItem

I am having trouble adding and removing a UISearchControllers searchBar to a UINavigationBar.
Here is what I am doing:
Add the searchBar to the view
searchController = [[UISearchController alloc]initWithSearchResultsController:nil];
searchController.searchResultsUpdater = self;
searchController.searchBar.delegate = self;
searchController.dimsBackgroundDuringPresentation = NO;
searchController.hidesNavigationBarDuringPresentation = NO;
searchController.searchBar.searchBarStyle = UISearchBarStyleProminent;
searchController.searchBar.barTintColor = [UIColor blackColor];
searchController.searchBar.tintColor = [UIColor darkGrayColor];
[searchController.searchBar setFrame:CGRectMake(0, 200, 320, searchController.searchBar.frame.size.height)];
[self.view addSubview:searchController.searchBar];
On button click add the searchBar to the navigationItem
This works as expected
[self.navigationController setNavigationBarHidden:false];
self.navigationItem.titleView = searchController.searchBar;
self.navigationItem.hidesBackButton = true;
And here is where I am getting the strange behaviour:
On another button click remove the searchBar from the nav bar and add it back to the view
[searchController.searchBar removeFromSuperview];
[self.navigationController setNavigationBarHidden:YES animated:true];
[self.view addSubview:searchController.searchBar];
[searchController.searchBar setFrame:CGRectMake(0, 200, 320, searchController.searchBar.frame.size.height)];
The searchBar is removed from the Nav Bar as expected, but it is not returned to the main view. ( well i can't see it anywhere)
I log the value of the search bar I can see that it has the frame that I have given it.
Any help here would be greatly appreciated,
Thanks
You should set navigationItem .titleView to nil first and setFrame: in main thread.
- (IBAction)addBar:(id)sender {
self.navigationItem.titleView = nil;
[searchController.searchBar removeFromSuperview];
[self.navigationController setNavigationBarHidden:NO animated:YES];
self.navigationItem.titleView = searchController.searchBar;
self.navigationItem.hidesBackButton = YES;
}
- (IBAction)removeBar:(id)sender {
self.navigationItem.titleView = nil;
[searchController.searchBar removeFromSuperview];
[self.view addSubview:searchController.searchBar];
[self.navigationController setNavigationBarHidden:YES animated:YES];
dispatch_async(dispatch_get_main_queue(), ^{
[self->searchController.searchBar setFrame:CGRectMake(0, 200, 320, self->searchController.searchBar.frame.size.height)];
});
}
By the way, I think it is better that put the search bar in a wrapper UIView when adding to the navigationItem.titleView.

UISearchController issues iOS8 vs iOS9

I ran into a problem where the UISearchController, when it animates the searchBar into the navigationBar, leaves the statusBar transparent and not the same color as the searchBar, like below:
I searched SO, and the below solution inspired by this question
- (void)willPresentSearchController:(UISearchController *)searchController {
self.navigationController.navigationBar.translucent = YES;
}
- (void)willDismissSearchController:(UISearchController *)searchController {
self.navigationController.navigationBar.translucent = NO;
}
fixes the problem for iOS9, but not for iOS8. I tried setting
self.extendedLayoutIncludesOpaqueBars = YES;
but with no effect. Also, setting
self.edgesForExtendedLayout = UIRectEdgeAll;
hides the initial searchBar under the navigationBar, so I cannot use it.
Here's my code for initiating a UISearchController under an opaque UINavigationBar:
UITableViewController *searchResultsController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
searchResultsController.tableView.dataSource = self;
searchResultsController.tableView.delegate = self;
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
self.searchController.delegate = self;
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.delegate = self;
self.searchController.searchBar.barTintColor = [UIColor whiteColor];
self.searchController.searchBar.frame = CGRectMake(0.0, 0.0, self.view.frame.size.width, 44.0); // Required for iOS8, not iOS9 though
[self.view addSubview:self.searchController.searchBar];
Any suggestions how to fix this for iOS8?

UISearchBar within UIViewController

I am trying to add a search bar programmatically to an UIView (not a UITableView). For the moment, I am just trying to set the delegates properly so that when I click the "enter" button, a message is printed:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSLog(#"enter button clicked");
[searchBar resignFirstResponder];
}
I already have some code working for an UITableViewController that I am trying to adapt. It looks like this (I am skipping all the parts of the code that are not relevant to the present discussion):
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) UITableViewController *resultsTableController;
- (void)viewDidLoad {
[super viewDidLoad];
self.resultsTableController = [[SearchResultsController alloc] init];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
self.searchController.searchResultsUpdater = self;
[self.searchController.searchBar sizeToFit];
self.searchController.delegate = self;
self.searchController.searchBar.delegate = self;
self.definesPresentationContext = YES;
self.tableView.tableHeaderView = self.searchController.searchBar;
}
Now the only line that doesn't transpose to the UIViewController case is the last one
self.tableView.tableHeaderView = self.searchController.searchBar;
My UIViewController is defined with a xib which contains a UIView called myView and a UISearchBar called searchBar. So I tried doing
self.myView = self.searchController.searchBar;
or
self.searchBar = self.searchController.searchBar;
but in the first case the searchBardoesn't even show and in the second case the delegation to self seems lost (nothing happens when I click enter).
What am I doing wrong ?
This is how you would add a UISearchBar to a UIViewController programmatically:
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, 0.0, kScreenWidth, 40.0)];
self.searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.searchBar.tintColor = kRunnerSearchBarTintColor;
if ([RunnerUtilities isIOS7orAbove]) {
self.searchBar.searchBarStyle = UISearchBarStyleProminent;
[self.searchBar setBarTintColor:[UIColor colorWithRed:185.0/255.0 green:195.0/255.0 blue:202.2/255.0 alpha:0]];
}
self.searchBar.delegate = self;
[self.view addSubview:self.searchBar];
Well, this is no more different than adding it from XIB file. First, search bar is a added as a subview to view of view controller and should be connected to search bar outlet defined in ViewController. Second, UIViewController must be set as delegate of the search bar. Please ensure you are following this and this should work.
EDIT::
If you are trying to use UISearchController within UIViewController, please try with following code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any custom init from here...
// Create a UITableViewController to present search results since the actual view controller is not a subclass of UITableViewController in this case
UITableViewController *searchResultsController = [[UITableViewController alloc] init];
// Init UISearchController with the search results controller
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
// Link the search controller
self.searchController.searchResultsUpdater = self;
// This is obviously needed because the search bar will be contained in the navigation bar
self.searchController.hidesNavigationBarDuringPresentation = NO;
// Required (?) to set place a search bar in a navigation bar
self.searchController.searchBar.searchBarStyle = UISearchBarStyleMinimal;
// This is where you set the search bar in the navigation bar, instead of using table view's header ...
self.navigationItem.titleView = self.searchController.searchBar;
// To ensure search results controller is presented in the current view controller
self.definesPresentationContext = YES;
// Setting delegates and other stuff
searchResultsController.tableView.dataSource = self;
searchResultsController.tableView.delegate = self;
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.delegate = self;
}

How to add UISearchBar to UIView?

I want to add a UISearchBar to an UIView instead of an UIViewController, the problem is that the init method of UISearchDisplayController needs an UIViewController as contentsController:.
I can see the UISearchBar correctly displayed in the view but if I click in it, the bar disappears. Here is my code I'm currently using:
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
// this was my approach, but this DOES NOT work
UIViewController *results = [[UIViewController alloc] init];
results.view.userInteractionEnabled = NO;
[self insertSubview:results.view aboveSubview:self.menuList];
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:results];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
self.tableView.tableHeaderView = self.searchBar;
Before:
After clicking into search bar:
In swift,
I use hidesNavigationBarDuringPresentation to solve this problem.
This problem seems like after the search bar is clicked, it will automatically hide the bar. And it will be fine after you click outside the view.
I add this line:
self.searchController?.hidesNavigationBarDuringPresentation = false;
Hope it works

UISearchDisplayController strange animation and offset

I have created a UITableViewController and added a UISearchDisplayController programmatically. There's no storyboard or nib file as I am doing everything programmatically. Everything seems to work perfectly except when I click on the search bar, it animates weirdly and there's some offset left to the bottom of the search bar.
Here's a video of the behaviour.
And here's the code of Table VC:
// Initialize Search Bar
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
self.searchBar.delegate = self;
self.tableView.tableHeaderView = self.searchBar;
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
self.searchController.delegate = self;
// Hide the search bar
[self.tableView setContentOffset:CGPointMake(0, 44)];
I also tried [self setEdgesForExtendedLayout:UIRectEdgeNone]; on the UITableViewController's implementation but it created another issue, although it seems to fix the animation by some extent leaving some gap at the top and the same gap at the bottom of search bar.
Edit: One more thing to noteā€”it can be seen in the video that the result table view is properly aligned with the search bar. So is there any problem with the implementation of main table view? They are same but the former is aligned properly so I am guessing there's a problem with the table view. What do you think?
iOS7 makes programmatically adding these elements unnecessarily difficult. After much testing in my own app, here's how I did it inside of my UITableViewController.
// _searchBar
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 44.0f)];
self.searchBar.delegate = self;
// _searchController
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:[self searchBar] contentsController:self];
self.searchController.delegate = self;
self.searchController.searchResultsDelegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsTableView.frame = [self.tableView frame];
// _tableView
self.tableView.tableHeaderView = [self.searchController searchBar];
Don't worry about hiding the searchBar, as the OS will reset everything to its original state when you hit cancel.

Resources