I just started to learn how to code with Swift in Xcode, I need some help regarding the search bar. I want to add a search field bar to my navigation bar in center, and next to it i want to add two items . So far I managed to add a UISearch to my navigation bar but once I try to add items next to it, it pushes my icons above the search field.
Pressed State
Normal State
Does anyone know what to add the two menu items next to it programmatically or in the storyboard? And how to make the search field centered and a bit thinner?
My code now:
override func viewDidLoad() {
super.viewDidLoad()
let searchController = UISearchController(searchResultsController: nil)
searchController.delegate = self as? UISearchControllerDelegate
let searchBar = searchController.searchBar
searchBar.tintColor = UIColor.white
searchBar.barTintColor = UIColor.white
if let textfield = searchBar.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
if let navigationbar = self.navigationController?.navigationBar {
navigationbar.barTintColor = UIColor.blue
}
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
}
Reddit Example
Okay, fixed it! Just used the code below. Now my next struggle is changing the background of the textfield.
//SEARCH
let searchController = UISearchController(searchResultsController: nil)
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.delegate = self as? UISearchBarDelegate
let frame = CGRect(x: 0, y: 0, width: 300, height: 44)
let titleView = UIView(frame: frame)
searchController.searchBar.backgroundImage = UIImage()
searchController.searchBar.frame = frame
titleView.addSubview(searchController.searchBar)
navigationItem.titleView = titleView
}
I am trying to change the background color of the search bar text field and i have searched and tried lots of solutions but those are not working.
So, please anyone can tell me the exact solution for that. How can we change the background color of the search bar text field?
/// used to prepare searchController inside navigation.
private func prepareNavigationSearchControllerSetup() {
self.title = AppConstant.kContacts
let search = UISearchController(searchResultsController: nil)
search.searchResultsUpdater = self
search.searchBar.cornerRadius = 10.0
search.searchBar.textField?.backgroundColor = .red
search.searchBar.textField?.tintColor = .yellow
self.navigationItem.searchController = search
self.navigationItem.hidesSearchBarWhenScrolling = false
}
extension UISearchBar {
var textField: UITextField? {
let subViews = subviews.flatMap { $0.subviews }
return (subViews.filter { $0 is UITextField }).first as? UITextField
}
}
After a lot more search I found the correct answer that is working for me.
if #available(iOS 11.0, *) {
if let textfield = search.searchBar.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {
backgroundview.backgroundColor = UIColor.white
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
}
You can try this
UITextField.appearance(whenContainedInInstancesOf: [type(of: searchController.searchBar)]).backgroundColor = .yellow
UITextField.appearance(whenContainedInInstancesOf: [type(of: searchController.searchBar)]).tintColor = .blue
Output
Edit : Full Code
var searchController = UISearchController()
let resultsTableController = Storyboard.Home.instantiateViewController(withIdentifier: "GlobalTableVC") as! GlobalTableVC
resultsTableController.tableView.delegate = self
resultsTableController.tableView.dataSource = self
resultsTableController.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "SearchCell")
searchController = UISearchController(searchResultsController: resultsTableController)
searchController.searchBar.placeholder = "Search"
searchController.dimsBackgroundDuringPresentation = true
searchController.searchBar.sizeToFit()
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.keyboardType = UIKeyboardType.alphabet
searchController.searchBar.tintColor = UIColor.white
searchController.searchBar.barTintColor = UIColor(hexString: "EB033B")
UITextField.appearance(whenContainedInInstancesOf: [type(of: searchController.searchBar)]).backgroundColor = .yellow
UITextField.appearance(whenContainedInInstancesOf: [type(of: searchController.searchBar)]).tintColor = .blue
searchController.searchBar.delegate = self
searchController.delegate = self
searchController.searchResultsUpdater = self
present(searchController, animated: true, completion: nil)
Since iOS 13:
if #available(iOS 13.0, *) {
searchController.searchBar.searchTextField.backgroundColor = .red
searchController.searchBar.searchTextField.tintColor = .yellow
}
I have added search bar in navigation bar large title. I am facing a flicker issue when the search bar is tapped to type into it.
Here is the video to the explain the issue:
The code I have written to achieve this is:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.title = "Leads"
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addNewLeadsAction(_:)))
let mysearchController = UISearchController(searchResultsController: nil)
mysearchController.searchResultsUpdater = self
mysearchController.searchBar.placeholder = "Search Lead"
mysearchController.searchBar.showsCancelButton = true
mysearchController.searchBar.barStyle = UIBarStyle.default
mysearchController.searchBar.backgroundColor = UIColor(patternImage: Common.gradientImage(view: (self.navigationController?.navigationBar)!))
if let textfield = mysearchController.searchBar.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.white
if let backgroundview = textfield.subviews.first {
backgroundview.backgroundColor = .white
backgroundview.layer.cornerRadius = 10
backgroundview.clipsToBounds = true
}
}
for searchBarView in mysearchController.searchBar.subviews{
for cancelButtonView in searchBarView.subviews{
if cancelButtonView.isKind(of: UIButton.self) {
let filterButton:UIButton = cancelButtonView as! UIButton
filterButton.isEnabled = true
filterButton.setTitle("", for: .normal)
let image1 = UIImage(named: "filterIcon")?.withRenderingMode(.alwaysTemplate)
filterButton.setImage(image1, for: .normal)
filterButton.contentMode = .scaleAspectFit
filterButton.tintColor = .white
filterButton.addTarget(self, action: #selector(filterAction(_:)), for: .touchUpInside)
}
}
}
self.navigationItem.searchController = mysearchController
self.definesPresentationContext = true
leadsTableView.reloadData()
}
Trying to make the transition smooth is what i'm looking to achieve.
Following are the things I have tried already:
iOS 11 UISearchBar in UINavigationBar
Navigation bar + Search controller + Large title: Hairline during scrolling
Any help will be appreciated
I have used simple UISearchController in UITableViewController. This has issue when I use search bar in first controller and which is hidden in next or back forth it shows UI glitch.
Here is how it looks>>
Here is below code for setting up navigation bar.
self.extendedLayoutIncludesOpaqueBars = true
let navigationBar = navigationController.navigationBar
let navigationBarTitleTextAttritbutes = [NSAttributedString.Key.foregroundColor: UIColor.white]
navigationBar.titleTextAttributes = navigationBarTitleTextAttritbutes
if #available(iOS 11.0, *) {
navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
navigationBar.prefersLargeTitles = false
}
navigationBar.isTranslucent = false
navigationBar.tintColor = UIColor.white
navigationBar.barTintColor = UIColor.purple
And For setting search controller used as below
self.searchController = UISearchController(searchResultsController: nil)
self.searchController.dimsBackgroundDuringPresentation = false
self.searchController.hidesNavigationBarDuringPresentation = false
self.searchController.hidesBottomBarWhenPushed = true
self.searchController.obscuresBackgroundDuringPresentation = false
let searchBarObj = self.searchController.searchBar
searchBarObj.delegate = self as? UISearchBarDelegate
searchBarObj.placeholder = "Search here"
searchBarObj.isTranslucent = false
searchBarObj.tintColor = .white
if #available(iOS 11.0, *) {
searchBarObj.tintColor = .white
searchBarObj.barTintColor = .white
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = true
} else {
let tintColor = UIColor.purple
searchBarObj.barTintColor = tintColor
searchBarObj.layer.borderColor = tintColor.cgColor
searchBarObj.layer.borderWidth = 1
if let table = tableview {
table.tableHeaderView = searchController.searchBar
}
}
I had been using the following code prior to iOS 11 to customize the appearance of the UISearchController search bar:
var searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.setDefaultSearchBar()
searchController.searchResultsUpdater = self
if #available(iOS 11.0, *) {
navigationItem.searchController = searchController
} else {
tableView.tableHeaderView = searchController.searchBar
}
extension UISearchBar {
func setDefaultSearchBar() {
self.tintColor = UIColor.blue
self.searchBarStyle = .minimal
self.backgroundImage = UIImage(color: UIColor.clear)
let searchBarTextField = self.value(forKey: "searchField") as! UITextField
searchBarTextField.textColor = UIColor.white
searchBarTextField.tintColor = UIColor.blue
searchBarTextField = .dark
}
}
However, the appearance of the search bar fails to update when running the same code on iOS 11.
iOS 10:
iOS 11:
Much of the attention to this question so far has focused on the text color of the search bar. I am looking at more than this - the background color, tint color, the search indicator, clear button color, etc.
I just found out how to set them: (with some help of Brandon and Krunal, thanks!)
The "Cancel" text:
searchController.searchBar.tintColor = .white
The search icon:
searchController.searchBar.setImage(UIImage(named: "my_search_icon"), for: UISearchBarIcon.search, state: .normal)
The clear icon:
searchController.searchBar.setImage(UIImage(named: "my_search_icon"), for: UISearchBarIcon.clear, state: .normal)
The search text:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedStringKey.foregroundColor.rawValue: UIColor.white]
The placeholder:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).attributedPlaceholder = NSAttributedString(string: "placeholder", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white])
The white background:
if #available(iOS 11.0, *) {
let sc = UISearchController(searchResultsController: nil)
sc.delegate = self
let scb = sc.searchBar
scb.tintColor = UIColor.white
scb.barTintColor = UIColor.white
if let textfield = scb.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
if let navigationbar = self.navigationController?.navigationBar {
navigationbar.barTintColor = UIColor.blue
}
navigationItem.searchController = sc
navigationItem.hidesSearchBarWhenScrolling = false
}
Taken from here.
To properly set the text typed into the search bar to white use (when using a dark field color):
searchController.searchBar.barStyle = .black
To set the textfield background color
if #available(iOS 11.0, *) {
if let textfield = searchController.searchBar.value(forKey: "searchField") as? UITextField {
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
}
However using something like
textfield.textColor = UIColor.blue
in the above does not seem to work.
Try setting the search bar's bar style.
searchController.searchBar.barStyle = UIBarStyleBlack;
Moving the call to setDefaultSearchBar into viewDidAppear should fix this.
You need to find the UISearchBar's underlying UITextField and change its text color.
Notice this only have effect when search controller is going to present (UISearchControllerDelegate.willPresentSearchController) or presented.
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// setup your search controller...
// set search controller's delegate
navigationItem.searchController?.delegate = self
}
}
extension ViewController : UISearchControllerDelegate {
func willPresentSearchController(_ searchController: UISearchController) {
// update text color
searchController.searchBar.textField?.textColor = .white
}
}
extension UISearchBar {
var textField: UITextField? {
for subview in subviews.first?.subviews ?? [] {
if let textField = subview as? UITextField {
return textField
}
}
return nil
}
}
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
Try it: searchController.<YOUR SEARCHBAR>.barStyle = .blackOpaque instead of self.searchBarStyle = .minimal.
Thus:
var searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.setDefaultSearchBar()
//Add this line below
searchController.searchBar.barStyle = .blackOpaque
searchController.searchResultsUpdater = self
if #available(iOS 11.0, *) {
navigationItem.searchController = searchController
} else {
tableView.tableHeaderView = searchController.searchBar
}
extension UISearchBar {
func setDefaultSearchBar() {
self.tintColor = UIColor.blue
//Delete this line below
self.searchBarStyle = .minimal
self.backgroundImage = UIImage(color: UIColor.clear)
let searchBarTextField = self.value(forKey: "searchField") as! UITextField
searchBarTextField.textColor = UIColor.white
searchBarTextField.tintColor = UIColor.blue
searchBarTextField = .dark
}
}
If you need to change the background colour of the textField in the searchBar, see my answer here:
https://stackoverflow.com/a/46315974/1109892
You have to access the UITextField inside the UISearchBar. You can do that by using
let textFieldInsideSearchBar = yourSearchbar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.textColor = yourcolor
OR