UISearchBar's scope buttons are covering the first row of results
I'm working with UISearchBar for the first time and can't quite make it do what I want.
When you activate the scope buttons, they cover the first row of the table. The only way to see all of your search results seem to be to hide the scope buttons when editing is finished; in my Googling on this I have seen that suggested.
I want the functionality that Mail has, where the scope buttons stay up as long as there is text in the search box, and you can see the search results change as you change the active scope button. But I can't figure out any way to make this happen without having the first row of the table covered by the scope buttons. You can't just scroll the table view down; the search bar is in the table view's header, so the whole thing scrolls together.
Suggestions appreciated!
Updated after trying Andrew's suggestion below.
One thing I forgot about is that in viewDidAppear I scroll the table view content up, so that the search box is off the top of the screen but can be scrolled down when needed. This is obviously part of my problem. So, in viewDidAppear I have
if (theSearchBar.showsScopeBar != YES) {
[self.tableView setContentOffset:CGPointMake(0, 44) animated:YES];
}
In searchBarShouldBeginEditing, I now have:
[self.navigationController setNavigationBarHidden:YES];
[self.tableView setContentOffset:CGPointMake(0, -44) animated:YES];
[UIView beginAnimations:@"searchBarUp" context:nil];
[UIView setAnimationDuration:1.0f];
searchBar.frame = CGRectOffset(searchBar.frame, 0, -44);
[UIView commitAnimations];
This gives the correct result, but when the scope bars come up, there is a gap between the top of the view and the top of the search bar, and the first row is covered. Then the scroll bar (with the scope buttons) slides up into place. This obviously doesn't look very good.
What I would expect the above code to do is:
hide the nav bar, which would put the top row of the table right below the status bar
scroll the table content back down, which would put the top of the search bar right below the status bar
move the search bar up so that there is a 44 pixel gap between the bottom of the search bar, to be filled in by the scope buttons
This does appear to be what happens, except you can see the gap left by the nav bar until the scroll bar moves up to meet it. You would think this could be fixed by hiding the nav bar last, but no... when I tried that I ended up with both the first row of the table covered and a nav bar sized hole between the status and search bars.
Another thing I find very odd is that if I use the above code snippet as is, except with animation:NO on the call to setContentOffset, I get a different result. In this case the first row of the table is not covered, but the search box is above the top of the view and cannot be scrolled down (it won't stay). Only the scope buttons are visible. It doesn't make sense to me that 开发者_如何转开发just turning off animation would change the outcome.
Now, you might think that with everything in the right place, displaying the search results would just work. But no. Even though the nav bar is now out of the picture, the search bar still comes up with a large gap above it, and the same adjustments to the table content and the search bar frame are required as above.
I should note that the code in viewWillAppear is only executed once, since we never leave the view, so it's not the case that the table is being readjusted upwards each time.
I would love to understand what's going on, as well as how to fix it, if anyone can help shed some light.
Updated again for clarity - when I say "fix it", what I mean is make it look good without visible gaps when the pieces are moving into place. I don't even necessarily want it animated; the sliding into position takes too long. But as I mentioned above, turning animation off makes things end up in the wrong place again.
Updated one last time - I got it to look much better by removing the animation block around the line to move the search bar. I guess that introduced a pause before the animation began. It's good enough now, at least for the moment. I'm still accepting Andrew's answer since he steered me in the right direction.
In the case of the Mail.app it looks like they hide the UINavigationBar with something like:
[self.navigationController setNavigationBarHidden:YES animated:YES];
Then using a UIView animation, they increase the size of the searchbar to take up the space that was filled by the navigationbar.
pseudo code:
[UIView beginAnimations:@"foo" context:NULL];
[UIView setAnimationDuration:1.0f];
CGRect newFrame = CGRectMake(0,0,self.view.frame.size.width, mySearchBar.frame.size.height);
mySearchBar.frame = newFrame;
//optionally, you could do something like this instead of setting a new frame
// mySearchBar.frame = CGRectOffset(mySearchBar.frame, 0, -44);
[UIView commitAnimations];
This would all go within the UISearchBarDelegate method
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
Then when the user cancels the search,
– searchBarCancelButtonClicked:
You'd reverse the animation, and show the navigationbar again.
You are using a UISearchDisplayController, right? If not, you should. It will take care of a lot of the work you are trying to do yourself, like hiding the navigation bar.
I have had the same problem. Since I wasn't using UISearchDisplayController( I wanted to avoid using the default search table view). So I rather went for the search bar directly. The problem was now the search bar is embedded under a table view ( you can check it in storyboard) . To fix the problem , you will have to embed a tableview and search bar separately under a UIView.
This is what I did, I'm using SearchViewController:
if #available(iOS 11.0, *) {
navigationItem.searchController = searchController
}
else{
tableView.tableHeaderView = searchController.searchBar
}
精彩评论