I have an iOS 7 application in XCode 5.0 that exhibits some strange behavior when tapping the search bar (UISearchBar).
My application has a Navigation Controller, and a Tab Bar Controller. Here is an example of what my Main.Storyboard looks like:
[Navigation Controller] -> [Tab Bar Controller] -> [Tab Item #1]
|
-------------> [Tab Item #2]
Each [] is a view controller
When I launch my application, I see the Tab Item 1 with the UISearchBar as shown in the screenshot below:
When I tap the UISearchBar, the search bar slides up to the top of the screen, but the Navigation Bar does not hide, and the view does not "slide up". This causes the app to look like this:
When I delete the Tab Bar Controller from the storyboard and connect the Navigation Controller directly to Tab Item #1 the Navigation Bar hides as expected.
How can I make the Navigation Bar hide when tapping the Search Bar? For an example of the functionality I am looking to reproduce, click the search bar under the "Contacts" tab of the default iOS7 "Phone" application.
For swift developers:
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
navigationController?.setNavigationBarHidden(true, animated: true)
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
navigationController?.setNavigationBarHidden(false, animated: true)
}
This will hide the navigation bar while search bar is active and show it again when search bar is inactive.
You can use the UISearchBar delegate methods to decide when to move the navigationbar out of the screen.
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
[UIView animateWithDuration:0.2 animations:^{
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
double yDiff = self.navigationController.navigationBar.frame.origin.y - self.navigationController.navigationBar.frame.size.height - statusBarFrame.size.height;
self.navigationController.navigationBar.frame = CGRectMake(0, yDiff, 320, self.navigationController.navigationBar.frame.size.height);
}];
}
-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{
[UIView animateWithDuration:0.2 animations:^{
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
double yDiff = self.navigationController.navigationBar.frame.origin.y + self.navigationController.navigationBar.frame.size.height + statusBarFrame.size.height;
self.navigationController.navigationBar.frame = CGRectMake(0, yDiff, 320, self.navigationController.navigationBar.frame.size.height);
}];
}
The following line will hide the navigation bar animatedly on activating search bar.
self.searchController.hidesNavigationBarDuringPresentation = true
You can set the top bar in the navigation controller for the list, to none and then add this to your tabBarController code:
self.navigationController.navigationBar.translucent= NO;
In the viewDidLoad method
You can do it with UISearchDisplayController method;
-(void)searchDisplayControllerWillBeginSearch:(mySearchDisplayController *)controller
{
self.searchResultsDataSource = self;
self.searchResultsTableView.delegate = self;
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1)
{
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
[UIView animateWithDuration:0.01 animations:^{
for (UIView *subview in self.searchBar.subviews)
subview.transform = CGAffineTransformMakeTranslation(0, statusBarFrame.size.height);
}];
}
}
-(void)searchDisplayControllerWillEndSearch:(mySearchDisplayController *)controller
{
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1)
{
[UIView animateWithDuration:0.01 animations:^{
for (UIView *subview in self.searchBar.subviews)
subview.transform = CGAffineTransformIdentity;
}];
}
}
Don't forget create a new class as a type of UISearchDisplayController and implement that code in it.
I solved the problem by adding constraint on Search Bar to Top Layout Guide and set its value to 0 and added a vertical spacing constraint to Search Bar and setting its value to 0;
I realize that this is probably too late to help you, but I ran into the same issue today!
I solved it by fixing the constraints of the search bar. Make sure the search bar has a constraint of 0px for its immediate top neighbor (the nav bar). Also make sure the tableview below the search bar has a constraint of 0px for its immediate top neighbor (the search bar).
Not sure of the exact problem you were facing, but that fixed it for me.
Related
Basically, I am including two buttons located below the navigation bar. And below these two buttons, there is a UITableView, with the UISearchBar as its header view. However, when I click the search bar, the animation moves very strange.
Then I try to use animation to move the UITableView together with the search bar to the top,
the animation goes like this
The code added to the table view is like this:
- (BOOL) searchBarShouldBeginEditing:(UISearchBar *)searchBar {
CGRect tableViewFrame = self.myTableView.frame;
tableViewFrame.origin.y = 0;
[UIView animateWithDuration:0.1
animations:^{
self.myTableView.frame = tableViewFrame;
}
completion:nil];
return YES;
}
I am wondering how to move the UISearchBar to the top of the screen, together with the whole table view with smooth animations.
- (BOOL) searchBarShouldBeginEditing:(UISearchBar *)searchBar {
[UIView animateWithDuration:0.1
animations:^{
[ searchBar setFrame:CGRectMake(searchBar.frame.origin.x, 0, searchBar.frame.size.width, searchBar.frame.size.height)];
[self.myTableView setFrame:CGRectMake(myTableView.frame.origin.x, searchBar.frame.size.height, self.myTableView.frame.size.width, myTableView.frame.size.height)];
}
completion:nil];
return YES;
}
try this code
I was just wondering how I can hide the tab item in the Tab Bar Controller for the current view controller which is selected
Remove intended index from controllersArray ex. (1)
NSMutableArray *controllersArray = [NSMutableArray arrayWithArray:self.tabBar.viewControllers];
[controllersArray removeObjectAtIndex: 1];
[self.tabBar setViewControllers:controllers animated:YES];
Check for this answer also I found this similar from your question Hide tab bar item and aligning other tab items
Hope this helps you.!!
Firstly, I don't think it's possible to hide a UITabBarItem - It inherits from UIBarItem but there is no hidden property - UIBarItem Documentation
You could try comparing the tab bars selectedViewController property against your current view controller? - Something like below might work..
if (self.tabBarController.selectedViewController == self) {
// Do Stuff
}
But even then I think you are going to find it hard to hide the tab bar item itself.
UIView *parent = self.tabBarController.tabBar.superview; // UILayoutContainerView
UIView *content = [parent.subviews objectAtIndex:0]; // UITransitionView
UIView *window = parent.superview;
[UIView animateWithDuration:0.2
animations:^{
CGRect tabFrame = self.tabBarController.tabBar.frame;
tabFrame.origin.y = CGRectGetMaxY(window.bounds);
self.tabBarController.tabBar.frame = tabFrame;
content.frame = window.bounds;
}];
On iOS 7, if I use the prefersStatusBarHidden method and return an instance variable that can be changed:
- (BOOL)prefersStatusBarHidden {
return self.statusBarShouldBeHidden;
}
And I change the instance variable, thus hiding the status bar, the navigation bar loses the 20pt of height that the status bar occupies. I don't want this, however. Is it possible to hide the status bar but keep the height of the navigation bar?
I found one solution to this problem at the following blogpost: http://www.factorialcomplexity.com/blog/2014/08/05/fixed-height-navigation-bar-on-ios7.html but his solution uses method swizzling on UINavigationBar, which I find unappealing.
UPDATE:
I figured out that subclassing UINavigationBar and providing a similar implementation to the swizzled solution solves this problem (Swift here, but the same works in Obj-C):
class MyNavigationBar: UINavigationBar {
override func sizeThatFits(size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
if UIApplication.sharedApplication().statusBarHidden {
size.height = 64
}
return size
}
}
Then update the class of the Navigation Bar in your storyboard, or use initWithNavigationBarClass:toolbarClass: when constructing your navigation controller to use the new class.
The navigation bar is keeping its height, it's just that the navigation bar and status bar don't have any separator between them (and have the same background), so they appear to be one thing, when, in fact, they are two. So what you really want is for the navigation bar to expand to take up the space previously occupied by both the navigation bar and the status bar.
I've done it like this before (heightCon is an IBOutlet to a height constraint on the navigation bar).
-(IBAction)hideStatusBar:(id)sender {
static BOOL hidden = YES;
[[UIApplication sharedApplication] setStatusBarHidden:hidden withAnimation:UIStatusBarAnimationSlide];
self.heightCon.constant = (hidden)? 64 : 44;
[UIView animateWithDuration:0.35 animations:^{
[self.navBar layoutIfNeeded];
}];
hidden = ! hidden;
}
I didn't get #rdelmar solution to work for me with the NSLayoutConstraint but I used his idea to come up with this very simple code.
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
[UIView animateWithDuration:0.35
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.navigationBar.top = 20;
}
completion:nil];
The options:UIViewAnimationOptionBeginFromCurrentState is very important here otherwise the animation is jerky because it starts from 0.
Cancel button in search bar don´t work in iOS 7 when search bar is initially hidden.
I follow this tutorial to create a search bar in tableview:
raywenderlich tutorial
There are a example project in this tutorial, is better use this project than my explanation :)
In iOS 5 and 6 works fine.
I have reviewed all delegates.
There are two possibilities. The first is to press the button when the bar is hidden, the second is to press the button when the bar is displayed (moving the table down with a gesture you can see the search bar)
If search bar is hidden initially cancel button don´t work, it don't call calcel delegate method:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
Sorry I can not explain it better.
Thanks
I googled all over internet and couldn't find a solution. so i changed the UItableview behaviour.
instead of [searchBar becomeFirstResponder]; I scroll down the tableview.
- (IBAction)goToSearch:(id)sender {
scroll down to show the table.
// CGRect newBounds = self.tableView.bounds;
// newBounds.origin.y =0;
//
// self.tableView.bounds = newBounds;
//[searchBar becomeFirstResponder];
CGPoint contentOffset=self.tableView.contentOffset;
contentOffset.y=0;
[self.tableView setContentOffset:contentOffset animated:YES];
}
in my ViewDidload:
// CGRect newBounds = self.tableView.bounds;
// newBounds.origin.y = newBounds.origin.y + searchBar.bounds.size.height;
// self.tableView.bounds = newBounds;
CGPoint contentOffset=self.tableView.contentOffset;
contentOffset.y=self.tableView.bounds.origin.y + searchBar.bounds.size.height;
self.tableView.contentOffset=contentOffset;
If found for some reasons, in iOS 7 , change table view bounds cause search bar to disappear.
Hope that helps.
That code work for me on iOS7:
- (IBAction)goToSearch:(id)sender {
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
[candySearchBar becomeFirstResponder];
}
put this code in your project it will work i have tested and it is working correctly
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchbar
{
[searchbar resignFirstResponder];
for (UIView *possibleButton in searchbar.subviews)
{
if ([possibleButton isKindOfClass:[UIButton class]])
{
UIButton *cancelButton = (UIButton*)possibleButton;
cancelButton.enabled = YES;
break;
}
}
}
This problem seems to come from the new behaviour of the translucent property in a navigation bar.
Since iOS 7 navigation bars are translucent by default. And it looks like it's overlapping the search bar when you display it after pressing a button.
Try to set in your controller:
float osVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (osVersion >= 7.0)
{
self.navigationController.navigationBar.translucent = NO;
}
This should quickly solve the problem.
But I think for a better fix you should see the iOS 7 transition guide where they explain how to handle translucent navigation bars.
Hope that helps.
I assume you have set _searchBar.delegate = self and implemented UISearchBarDelegate in your class.
This is how you do it:
- (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
[searchBar setShowsCancelButton:YES animated:YES];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{ // called when cancel button pressed
searchBar.text = nil;
//hide cancel button
[_searchBar setShowsCancelButton:NO animated:YES];
[searchBar resignFirstResponder];
}
I'm working on an application and need to hide the UINavigationBar (and toolbar) to provide a fullscreen mode in the in-app browser.
When the app run this code the animation work just fine.
[self.navigationController setNavigationBarHidden:YES animated:YES];
[self.navigationController setToolbarHidden:YES animated:YES];
When I want to exit from the full-screen mode the animation isn't smooth at all.
[self.navigationController setNavigationBarHidden:NO animated:YES];
[self.navigationController setToolbarHidden:NO animated:YES];
During the animation a black rectangle is visible under the navigation bar, I think it is the UIWebView that resize itself (the toolbar animation work just fine.)
Any idea on how I can solve this problem?
Instead of using setNavigationBarHidden:animated: for hiding the navigation bar, try this:
In your view controller's viewDidLoad compute different frames for your navigation bar and your view:
// The normal navigation bar frame, i.e. fully visible
normalNavBarFrame = self.navigationController.navigationBar.frame;
// The frame of the hidden navigation bar (moved up by its height)
hiddenNavBarFrame = normalNavBarFrame;
hiddenNavBarFrame.origin.y -= CGRectGetHeight(normalNavBarFrame);
// The frame of your view as specified in the nib file
normalViewFrame = self.view.frame;
// The frame of your view moved up by the height of the navigation bar
// and increased in height by the same amount
fullViewFrame = normalViewFrame;
fullViewFrame.origin.y -= CGRectGetHeight(normalNavBarFrame);
fullViewFrame.size.height += CGRectGetHeight(normalNavBarFrame);
When you want to go fullscreen:
[UIView animateWithDuration:0.3
animations:^{
self.navigationController.navigationBar.frame = hiddenNavBarFrame;
self.view.frame = fullViewFrame;
} completion:^(BOOL finished) {
}];
When you want to return to normal:
[UIView animateWithDuration:0.3
animations:^{
self.navigationController.navigationBar.frame = normalNavBarFrame;
self.view.frame = normalViewFrame;
} completion:^(BOOL finished) {
}];
Tested this in the iOS 5.1 emulator. Hope you can use that. The "black rectangle" must be the default background color of your window, i.e. a gap between your navigation bar and your view.