I have an issue with a search bar that behaves in a strange way when it becomes a firstResponder and when it resigns.
The search bar is added as the header of a table view
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 44.0f)];
self.searchBar.translucent = NO;
self.searchBar.barTintColor = [UIColor grayColor];
self.tableView.tableHeaderView = self.searchBar;
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar
contentsController:self];
self.searchController.searchResultsDataSource = self;
The view controller is set a left panel of JASidePanelController and it hides the center panel when the keyboard shows or hides :
- (void)keyboardWillAppear:(NSNotification *)note
{
[self.sidePanelController setCenterPanelHidden:YES
animated:YES
duration:[[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
self.searchBar.showsCancelButton = YES;
}
- (void)keyboardWillDisappear:(NSNotification *)note
{
[self.sidePanelController setCenterPanelHidden:NO
animated:YES
duration:[[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
self.searchBar.showsCancelButton = NO;
}
Normal state
When the search bar becomes a firstResponder it either moves about a point up or point down randomly
And When the search bar resigns it animates up to reach the window origin and then back to its natural frame
Here is a sample project reproducing the bug.
EDIT :
As per #kwylez suggestion, the unwanted animation that the search bar makes when it resigns can be avoided by:
self.searchBar.clipsToBounds = YES;
I solved this issue by creating a UIView with ClipBounds sets to YES and then add subview the searchbar inside it.
Then include it in tableview header. its working now.
Thanks
You initialize a search display controller with a search bar and a view controller responsible for managing the data to be searched. When the user starts a search, the search display controller superimposes the search interface over the original view controller’s view and shows the search results in its table view.
customized your searchbar view
Fixed - UISearchBar-bug-master
I traced the issue to the function "_layoutSidePanels" in the JASidePanelController.
In your app delegate, I commented out the following code and it seems to fix the grey view growing and shrinking.
rootViewController.shouldResizeLeftPanel = YES;
If you follow the code through, when the searchbar is selected you call setCenterPanelHidden, which subsequently calls _layoutSidePanels, which runs the following code:
if (self.leftPanel.isViewLoaded) {
CGRect frame = self.leftPanelContainer.bounds;
if (self.shouldResizeLeftPanel) {
frame.size.width = self.leftVisibleWidth;
}
self.leftPanel.view.frame = frame;
}
Changing the frame of the sidepanel seems to be the cause, and as I said commenting that code out fixes the issue on my end.
Edit: Also at first it seemed like the search bar was moving up and down a point, but upon further inspection it appears that it is always slightly underneath the navigation bar, but you don't notice it until you select the searchbar and the rest of the view "greys" out, so that little space that was white between the blue nav bar and light grey search bar becomes dark grey like the rest of the tableview below.
Edit #2: Took me a while, but I managed to figure out where the heck that grey mask was coming from. Your UISearchDisplayController is what is responsible for the greyish background that appears when the search bar becomes first responder, and when I removed the following two lines of code the issue you were seeing went away:
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchController.searchResultsDataSource = self;
Doing this was just to demonstrate the cause of the issue, but removing those lines of code disable whatever functionality you were going to gain from using the search display controller. I don't know exactly what you're hoping to do, so I can't really give you any advice about how to proceed, but hopefully I've pointed you in the right direction as to the causes!
Related
I am trying to add a UISearchBar to my UINavigationItem but the scope bar is showing behind the search bar. Any ideas to fix that problem?
iOS: 11.2
xCode: 9.2
my code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.mySearchBar = [[UISearchBar alloc] init];
self.mySearchBar.delegate = self;
self.mySearchBar.scopeButtonTitles = #[#"item 1", #"item 2", #"item 3"];
self.navigationItem.titleView = self.mySearchBar;
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
[self.mySearchBar setShowsScopeBar: TRUE];
[self.mySearchBar setShowsCancelButton:TRUE animated:TRUE];
return TRUE;
}
the result:
Context
The problem is that UINavigationBar provides a very specific and familiar iOS style that Apple wants to keep the same across apps. Default navigation bars don't expand to fit their contents.
When you set set the titleView of navigation item, you are expected to lay out the contents in that view based on the size of the navigation bar, not the other way around.
Solutions
There are several possible solutions:
Change the behavior of that instance of UINavigationBar (not recommended).
Place the UISearchBar underneath the navigation bar as a regular subview.
Use UISearchController
The first option should definitely not be your first solution because it requires you to solve many thorny issues. Use as a last resort.
Option 2 requires the following code changes. Replace self.navigationItem.titleView = self.mySearchBar with:
[self.view addSubview:self.mySearchBar];
UILayoutGuide *guide = self.view.safeAreaLayoutGuide;
[self.mySearchBar.topAnchor constraintEqualToAnchor:guide.topAnchor].active = YES;
[self.mySearchBar.rightAnchor constraintEqualToAnchor:guide.rightAnchor].active = YES;
[self.mySearchBar.leftAnchor constraintEqualToAnchor:guide.leftAnchor].active = YES;
And you are also missing code to resize the UISearchBar after showing the scope bar. The view does not resize itself. So, in your searchBarShouldBeginEditing: method, add this line just before return: [self.mySearchBar sizeToFit];
The third solution may be easier for you depending on your use case. That is, use UISearchController, which includes it's own UISearchBar anchored at the top of the screen. It would look just like solution #2 above as shown in the image below:
Here is a great tutorial on using UISearchController if you are interested.
I have a search bar as a title view for my navigation bar.
And it looks like this, the way I want it to look like:
But when I tap on it, it just slides to top and becomes inaccessible
Here is the code I used to configure it:
- (void)configureSearchBar
{
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchBar.delegate = self;
self.navigationItem.titleView = self.searchController.searchBar;
}
Is there any way to fix this kind of problem?
self.searchController.hidesNavigationBarDuringPresentation = NO
Adding this line has solved this problem or me. The reason of this problem was that my search bar was set as a title view for my navigation bar and the property hidesNavigationBarDuringPresentation was set to YES by default. Setting this property to NO solves this kind of problem.
I implemented a horizontal table view and it looks like this
The category bar, Dining Shopping something, is a horizontal table view and here is the implementation code.
LogInfo(#"Show Category Table start");
// add categories to be subview controller
self.categoriesTable = [[UITableView alloc] init];
self.categoriesTable.transform = CGAffineTransformMakeRotation(-M_PI * 0.5);
[self.categoriesTable setFrame:CGRectMake(0, 64, SCREENWIDTH, 44)];
self.categoriesTable.showsVerticalScrollIndicator = NO;
self.categoriesTable.showsHorizontalScrollIndicator = NO;
self.categoriesTable.pagingEnabled = YES;
self.categoriesTable.delegate = self;
self.categoriesTable.dataSource = self;
self.categoriesTable.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.superView addSubview:self.categoriesTable];
LogInfo(#"Show Category Table Finished");
self.categoriesTable.backgroundColor= [UIColor redColor];
It works as expect but if I change view, for example, I click any button to go to other view and go back to this view. The tableview looks like this
This problem also happpens even if I disable the bounce effect of the table view. Does anyone know how to solve this problem? Thanks!
Rather than applying a transform to the table to make it horizontal, use a collectionView with a horizontal layout.
Edit: If you want to continue using your current setup, try disabling automaticallyAdjustsScrollViewInsets on your view controller.
self.automaticallyAdjustsScrollViewInsets = NO
Edit 2: If you're curious, since iOS 7 every view controller looks at its topmost/first scroll view and adjusts its contentInsets to compensate for the navigation bar transparency which is enabled by default. In this case of course, such behaviour isn't desired at all.
I have a UISearchBar in a tableviewcontroller like so:
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
self.tableView.tableHeaderView = self.searchBar;
When the user taps in the search bar to search, the searchbar expands to show the cancel button, but then also moves down about 20 pixels, so in effect there is a 20 pixel blank space above the searchbar between the search bar and the navigation bar. I don't understand the moving down behavior and what I can do to prevent it. Does anyone know what exactly might cause that to happen and how I can prevent it?
I was having the same issue, although with a UISearchBar being presented by UISearchController. For me, removing the line
self.edgesForExtendedLayout = UIRectEdgeNone;
from the presenting VC's viewDidLoad method stopped the search bar dropping down.
I have placed a UISearchBar in my UITableView.tableHeaderView. However it covers the searchBar by placing the viewable top to the first section header. I can only see the searchBar when I drag the tableView down. It is half covered and then can not be selected because releasing the tableView scrolling will rubber band it back out of view. Please help.
The following is placed in my UITableViewController viewDidLoad method:
UISearchBar *theSearchBar = [[UISearchBar alloc] init];
theSearchBar.delegate = self;
self.searchBar = theSearchBar;
[theSearchBar release];
self.tableView.tableHeaderView = self.searchBar;
The result is the following screenshots: http://imagebin.ca/view/6qNiwHR.html
It turns out that it was a sizing issue. I found a tutorial that places the following code in the set up:
[theSearchBar sizeToFit];
which make everything look perfect.
Since UISearchDisplayController uses an already established UISearchBar it doesn't eliminate the problem.
I think the tableHeaderView is not the best place to put your search bar.
I usually use a UISearchDisplayController:
searchController = [[UISearchDisplayController alloc]
initWithSearchBar:theSearchBar contentsController:self];
searchController.delegate = self;
searchController.searchResultsDataSource = self;
searchController.searchResultsDelegate = self;
It's pretty straight-forward and give some functions for searching (you have to implement them in the delegate/datasource, in this case your controller).
I usually do it from a nib but i think you just have to assign it to your viewcontroller :
self.searchDisplayController=searchController;
And if it doesn't show the view, you should add the view to the tableView directly.
You can look at the reference, or ask if you have some problems.