UISearchBar presented by UISearchController in table header view animates too far when active
IosUitableviewIos8UisearchbarUisearchcontrollerIos Problem Overview
I am using UISearchController to present a search bar inside the header view of a tableview:
...
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.presentingTVC.tableView.tableHeaderView = self.searchController.searchBar;
[self.searchController.searchBar sizeToFit];
self.presentingTVC.tableView.tableHeaderView = self.searchController.searchBar;
(where setting the tableHeaderView property twice is necessary as otherwise the header view overlaps the first row, c.f.a couple of answers on S.O. )
This is how it looks, perfectly in position when inactive:
The search bar should just stay in place when active - I don't want it to move up to hide the navigation bar. But it unexpectedly animates down, leaving a blank space between it and the navigation bar:
Here's a video of weird search bar animation
If I just use a search bar separately from UISearchController, it does not show the same behaviour when it becomes active.
In my presenting view controller, I have self.definesPresentationContext = YES;
and self.navigationController.navigationBar.translucent = YES;
, and in IB none of the "extend edges" boxes are active (all seemed to be possible things that could throw search presentation off, from reading around).
Does anyone know how I can stop the search bar from animating down?
Ios Solutions
Solution 1 - Ios
Old question but I was able to solve this issue by setting
self.extendedLayoutIncludesOpaqueBars = YES;
on my view controller. I think is issue is caused by having an opaque navigation bar but setting hidesNavigationBarDuringPresentation
to NO
on your search controller, causing the search bar to incorrectly position itself when focused.
Solution 2 - Ios
Ok so I finally figured out a solution for myself. Though it's more than likely we have other things in our code / storyboard (that's why this is a hard question to answer), for the most part I followed Apple's tutorial on UISearchController: (https://developer.apple.com/library/ios/samplecode/TableSearch_UISearchController/Introduction/Intro.html)
Just about all my code is identical to theirs, but I couldn't get the search bar to not jump when clicking inside of it. So what I did was check "under opaque bars" for both the original table view and the search results table view in my storyboard. That got the search bar to stop jumping.
But there was one last issue, which was the fact that the first row of the results table view was hidden by the search bar. In order to fix that I added self.tableView.contentInset = UIEdgeInsetsMake(kHeightOfTableViewCells, 0, 0, 0);
to the viewDidLoad
method of my results table view. Voila!
Solution 3 - Ios
I was able to prevent UISearchBar
from shifting down by removing the following line from my ViewController:
self.definesPresentationContext = YES;
Solution 4 - Ios
definesPresentationContext = true
override func viewDidLoad() {
super.viewDidLoad()
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = true
searchController.searchBar.searchBarStyle = UISearchBarStyle.Prominent
self.tableView.tableHeaderView = searchController.searchBar
definesPresentationContext = true
Solution 5 - Ios
My turn. I also had this problem when I followed the WWDC sample code.
I noticed that if I didn't set the scopeButtonTitles property of the searchBar, the searchBar would not be visible. Upon closer inspection, it just had a frame of CGRectZero. This means that setting the scopeButtonTitles sets the frame behind the scenes. So If don't want to show any scopeButtonTitles, but still want to not have to hardcode UISearchBar to a specific height, set the scopeButtonTitles to an empty array.
self.searchController = UISearchController(searchResultsController: nil)
self.searchController.searchResultsUpdater = self
self.searchController.searchBar.scopeButtonTitles = []
self.tableView.tableHeaderView = self.searchController.searchBar
Setting the scopeButtonTitles to an array of 1 strings will not display the scope button titles, but still have logic to deal with the view, essentially screwing up the layout.
Props to Apple's QA team (applicable to iOS 8)
Solution 6 - Ios
I ran to this problem just recently and none of the solutions worked for me. Maybe because my UI is more complex (My table view with search supports in contained in UITabController inside a UiNavigationController) anyway, none of the above worker. I could simply solve my problem by this very neat piece of code I found at: UISearchController Not Redisplaying Navigation Bar on Rotate
- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar
{
if (bar == searchController.searchBar) {
return UIBarPositionTopAttached;
}
else { // Handle other cases
return UIBarPositionAny;
}
}
One more thing to add: after setting all my controller's hierarchy to extend under opaque and top bars, my search bar started to appear hidden under navigation bar and would've appeared right just after a rotation might happened. that was a cue for me that there is some lay out error and some information abut my layout was not right. this delegate method helps my controller understand the situation about the otherwise nomad search bar!
Solution 7 - Ios
Found it! This seems to be the offensive line in viewDidLoad
of the presenting vc:
self.edgesForExtendedLayout = UIRectEdgeNone;
Removed that and the search bar stayed in place as predicted.
Solution 8 - Ios
Solution 9 - Ios
for iOS 11 & swift 4, set the line bellow in the viewController resolved my issue (searchBar jump down):
self.edgesForExtendedLayout = .bottom
Solution 10 - Ios
I guess you set UISearchBar frame.original.y = 64
there are the code
if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
[self setEdgesForExtendedLayout:UIRectEdgeNone];
}
searchBar.frame = CGRectMake(0, 0, 376, 44);
wash can help you
Solution 11 - Ios
In my case, setting the nav bar to self.navigationController.navigationBar.translucent = NO;
fixed the problem. It seems that the search bar presentation layer doesn't take into account the translucence of the nav bar when laying out the search bar.
I realize this isn't a perfect solution, because the translucence of the nav bar can throw off layout elsewhere, but it at least fixes the problem in the case where a non-translucent nav bar is a possibility.
Solution 12 - Ios
As mentioned in the first post everyone needed a different solution. So here is mine. I had to combine two things mentioned on this page, namely:
Swift 2:
navigationController?.navigationBar.translucent = true
edgesForExtendedLayout = .None
Solution 13 - Ios
its very simple just do clipsToBounds = true of header view of table view in witch search bar is added.
countryTableView.tableHeaderView?.clipsToBounds = true
Solution 14 - Ios
If you use UINavigationController
and TabBar
you can't use:
self.extendedLayoutIncludesOpaqueBars = true
You would need this solution: https://stackoverflow.com/a/46151063/3369381