Notice how the searchBar magnifying glass and placeholder text both shift over on dismissal:
Is there any way I could dismiss this search bar without the text and icon moving over? See the animation of the Music app for the animation I am trying to achieve.
I have a UISeachBar that gets presented when the search button is clicked in a nav bar.
#IBAction func searchButtonPressed(sender: AnyObject) {
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.searchBar.delegate = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = false
presentViewController(searchController, animated: true, completion: nil)
}
Now when the cancel button is pressed, I want the whole view to move up without seeing the SearchBar icon and placeholder text slide to the center of the searchBar as the view moves up off screen.
I know there is the method searchBarCancelButtonClicked(searchBar:), but this seems to automatically dismiss the SearchBar and I don't know how to control that.
How can I make the SearchBar dismiss like the one in the Music app?
EDIT: Here is the only delegate method I am using:
func updateSearchResultsForSearchController(searchController: UISearchController) {
masterFilter.removeAll()
filterContentForSearchText(searchController.searchBar.text!)
tableView.reloadData()
}
This is how I have achieved this. It is simple and easy.
extension UIViewController {
func setNavigationBarItem() {
let searchaButton = UIButton.init(frame: CGRectMake(0, 0, 30, 30))
searchaButton.setBackgroundImage(UIImage(named: "search.png"), forState: UIControlState.Normal)
searchaButton.addTarget(self, action: #selector(self.searchPressed), forControlEvents: UIControlEvents.TouchUpInside)
let rightButton: UIBarButtonItem = UIBarButtonItem.init(customView: searchaButton)
navigationItem.rightBarButtonItem = rightButton
}
public func searchPressed(){
var searchController: UISearchController!
// Create the search results view controller and use it for the UISearchController.
let searchResultsController = storyboard!.instantiateViewControllerWithIdentifier("SearchResultController") as! SearchResultsViewController
// Create the search controller and make it perform the results updating.
searchController = UISearchController(searchResultsController: searchResultsController)
searchController.searchResultsUpdater = searchResultsController
searchController.hidesNavigationBarDuringPresentation = false
// Present the view controller.
presentViewController(searchController, animated: true, completion: nil)
}
}
Note:
This code is for old swift version.
I hope this will help you.
The searchBar expands to the right because the search is being cancelled, and the cancel button is disappearing.
Instead of canceling the search and triggering that animation, simply explicitly dismiss the search controller.
You can do this by setting
searchController.active = false
To make this animation work, you'll need to understand custom UIViewController transitions. Within the UISearchBarDelegate method -searchBarCancelButtonClicked(searchBar:), you'll need to do a few things:
Hide the UINavigationBar on the UISearchController dismissal
Animate the UITableView to the bottom of the frame and fade out.
If you're presenting search modally, ensure that you're setting the modalPresentationStyle to UIModalPresentationCurrentContext.
Related
I am using UISearchController in a Large header style. But when I push to the next view controller and coming back to the same controller again my UIView hides by navigation bar.
See Video
https://drive.google.com/open?id=1tb5Eeni-79uomBGl1GPEcESDSYOfrZ7v
I can't reproduce your error, but I'll post my test code, as it can help you.
I suggest that you write this code in a BaseViewController: UIViewController and extend it in your ViewControllers for define Large Titles:
self.navigationController?.navigationBar.prefersLargeTitles = true
Define your UISearchController and set your Instance.
var resultSearchController: UISearchController!
resultSearchController = UISearchController(searchResultsController: nil)
resultSearchController.searchResultsUpdater = self
tableView.tableHeaderView = resultSearchController.searchBar
Finally, you can try to close the Search keyboard when the screen disappears, like this:
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
resultSearchController.searchBar.endEditing(true)
}
Hope this helps.
Adding following line in viewwillappear resolves my issue
extendedLayoutIncludesOpaqueBars = true
I have a problem with search bar. I need to create a table view with a search button in the right corner, and when I click on it, it should show the search bar.
My code is here:
// Search controller
searchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.delegate = self
controller.searchBar.delegate = self
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.hidesNavigationBarDuringPresentation = true
controller.searchBar.sizeToFit()
return controller
})()
And here is action:
// Search action
#IBAction func search(sender: UIBarButtonItem) {
print("Open search")
searchController.active = true
if searchController.searchBar.isFirstResponder() == false {
searchController.searchBar.becomeFirstResponder()
}
}
When I click on the button, nothing happens (only prints text in console), and what I want is in the image below:
Your class needs to conform to a UISearchBarDelegate, I'm not sure if you've done that already. Also make sure you present the search view
From Apple's Docs:
The UISearchBarDelegate protocol defines the optional methods you implement to make a UISearchBar control functional. A UISearchBar object provides the user interface for a search field on a bar, but it’s the application’s responsibility to implement the actions when buttons are tapped. At a minimum, the delegate needs to perform the actual search when text is entered in the text field.
Here's a sample from my app
#IBAction func searchAction(sender: UIBarButtonItem) {
// Create the search controller and specify that it should present its results in this same view
searchController = UISearchController(searchResultsController: nil)
// Set any properties (in this case, don't hide the nav bar and don't show the emoji keyboard option)
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.keyboardType = UIKeyboardType.ASCIICapable
// Make this class the delegate and present the search
self.searchController.searchBar.delegate = self
presentViewController(searchController, animated: true, completion: nil)
}
Old question, but want to add a new answer (maybe things changed since the original answer from 2016).
Simply call this on the view controller, assuming you already set up the search controller. No need to conform to UISearchBarDelegate:
Swift 5
present(searchController, animated: true, completion: nil)
I currently have my UISearchController set up so it is presented over the nav bar once the search icon is clicked.
var searchController: UISearchController!
#IBAction func searchMe(sender: UIBarButtonItem) {
// Create the search results view controller and use it for the `UISearchController`.
let searchResultsController = storyboard!.instantiateViewControllerWithIdentifier(SearchResultsViewController.StoryboardConstants.identifier) as! SearchResultsViewController
// Create the search controller and make it perform the results updating.
searchController = UISearchController(searchResultsController: searchResultsController)
searchController.searchResultsUpdater = searchResultsController
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.tintColor = Colors.blue
searchController.searchBar.barTintColor = UIColor.whiteColor()
// Present the view controller.
presentViewController(searchController, animated: true, completion: nil)
}
I am using a different searchResultsController than the current table view to display results. The problem is that when a cell is selected in the searchResultsController a segue is performed to a new view controller (the users profile) and there is no navigation bar.
I need a back button to appear to take the user back to the searchResultsController. I have tried a bunch of different segues, setting the nav bars on the storyboard but nothing seems to work. My initial thought was to make this line of code:
searchController = UISearchController(searchResultsController: searchResultsController)
point to a nav controller with searchResultsController as its root view controller but I had no luck. Any help is great! Thank you!
I have two buttons on top of a map. If you tap the search button the buttons animate to switch places; which is what i want. However if you cancel the search I would like the buttons to switch back. I tried this
self.searchDisplayController.active = false
(which i know is depreciated)
inside of an if statement and it did not work
I was wondering what code I could put inside an if statement would do what I want to do.
Here is the search button code
#IBAction func showSearchBar(sender: AnyObject) {
searchController = UISearchController(searchResultsController: nil)
searchController.hidesNavigationBarDuringPresentation = false
self.searchController.searchBar.delegate = self
presentViewController(searchController, animated: true, completion: nil)
setButtonPosition("buyer")
}
the last line
setButtonPosition("buyer")
is what switches the button position
Thanks
I have UICollectionView. On clicking search button in UINavigationBar, I am adding the UISearchController's searchbar as titleview for UINavigationItem. For iPhone it is working properly. For iPad the cancel button is not shown. The Searchbar alone takes the entire width.
Can anyone help me out on this?. Thanks in advance.
iOS7 does not show the cancel button when added to a navigation bar.You can put searchbar in another view like this.
UISearchBar *searchBar = [UISearchBar new];
searchBar.showsCancelButton = YES;
[searchBar sizeToFit];
UIView *viewForSearchBar = [[UIView alloc]initWithFrame:searchBar.bounds];
[viewForSearchBar addSubview:searchBar];
self.navigationItem.titleView = viewForSearchBar;
I had the same problem, on iPhone the search cancel was shown well, but on iPad it didn't.
The workaround of wrapping the UISearchBar in another UIView didn't work well for me since it had different appearance and wrong width on rotation.
My solution is a simple one - use search WITHOUT cancel, and add cancel as a UIBarButtonItem.
Added rightBarButtonItem with selector will work fine for me. And adding searchBar inside view before setting to navigation title view was not showing properly.
Code:-
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(self.dismissView))
func dismissView() {
if self.controller?.navigationController?.popViewController(animated: true) == nil {
self.controller?.dismiss(animated: true, completion: nil)
}
}
As per apple documentation setShowsCancelButton
Cancel buttons are not displayed for apps running on iPad, even when
you specify YES for the showsCancelButton parameter.
I am not sure about the alternate but this is what apple provides us.
Try this. Add a checkmark for shows cancel button.
Swift version :-
I tried the #Nikita Khandelwal method, but still it doesn't fit for ipad view. Here is the swift code, which was given as corrected answer :-
let searchBar: UISearchBar = UISearchBar()
searchBar.showCancelButton = true
searchBar.placeholder = "Search Your Job Title"
searchBar.fitToSize()
searchBar.delegate = self //do not need if you delegate searchBar
let viewForSearchBar: UIView = UIView(frame: searchBar.bounds)
viewForSearchBar.addSubview(searchBar)
self.navigationItem.titleView = viewForSearchBar
********* But There is another way to set cancel button correctly and fit for the view :-
Set search bar as the Navigation bar title view :-
let searchBar: UISearchBar = UISearchBar()
searchBar.showCancelButton = true
searchBar.placeholder = "Search Your Job Title"
searchBar.delegate = self //do not need if you delegate searchBar
self.navigationItem.titleView = searchBar
Drag and drop Bar button to the right side of the view controller & name it as Cancel.
Then connect that button to this function :-
#IBAction func iPadCancelButton(sender: AnyObject) {
UIApplication.sharedApplication().sendAction("resignFirstResponder", to:nil, from:nil, forEvent:nil)
self.dismissViewControllerAnimated(true, completion: nil)
}
For iOS 13 built with Xcode 11, I'm needing to set manually set the display value on the cancel button, depending on whether the search controller is visible