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
Related
The UI in my searchbar is behaving differently than expected.
I want it to look like this:
In iOS 13 it looks like this:
And in iOS 12 it looks like this:
I am configuring the searchbar in ViewDidLoad with this:
guard let searchField = searchBar.value(forKey: "searchField") as? UITextField else { return }
searchBar.backgroundColor = .red
searchField.backgroundColor = UIColor.black.withAlphaComponent(0.3)
searchField.textColor = .white
searchField.leftView?.tintColor = .white
searchField.attributedPlaceholder = NSAttributedString(string: "Search", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
I've tried to create your searchBar but I didn't test it. You can find answers to your questions from the code snippet. You need to add the UISearchBar extension also to your project to use some methods in the snippet.
searchBar.tintColor = UIColor.white
searchBar.searchBarStyle = .default
searchBar.placeholder = "Search"
searchBar.setTextFieldPlaceholderColor(color: UIColor.white)
searchBar.backgroundColor = UIColor.red
searchBar.setImage(UIImage(named:"searchIcon"), for: .search, state: .normal)
if #available(iOS 13.0, *) {
searchBar.searchTextField.backgroundColor = UIColor.black.withAlphaComponent(0.3)
searchBar.setBackgroundImage(UIImage(), for: .any, barMetrics: .default)
searchBar.searchTextField.textColor = UIColor.white
searchBar.searchTextField.font = UIFont.systemFont(ofSize: 12)
} else {
searchBar.removeBackgroundImageView()
searchBar.setTextFieldBackground(color: UIColor.black.withAlphaComponent(0.3))
}
UISearchBar extension
extension UISearchBar {
//use for iOS 12 and below
func removeBackgroundImageView(){
if let view:UIView = self.subviews.first {
for curr in view.subviews {
guard let searchBarBackgroundClass = NSClassFromString("UISearchBarBackground") else {
return
}
if curr.isKind(of:searchBarBackgroundClass){
if let imageView = curr as? UIImageView{
imageView.removeFromSuperview()
break
}
}
}
}
}
func setTextFieldBackground(color : UIColor) {
for subView in self.subviews {
for subView1 in subView.subviews {
if subView1.isKind(of: UITextField.self) {
subView1.backgroundColor = color
(subView1 as? UITextField)?.font = UIFont.systemFont(ofSize: 12)
}
}
}
}
func setTextFieldPlaceholderColor(color : UIColor) {
for subView in self.subviews {
for subView1 in subView.subviews {
if subView1.isKind(of: UITextField.self) {
if let placeholder = (subView1 as! UITextField).placeholder {
(subView1 as! UITextField).attributedPlaceholder = NSAttributedString(string:placeholder,attributes: [NSAttributedString.Key.foregroundColor: color])
}
}
}
}
}
}
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 know how to set the appearance for a independent UISearchBar, just like the following.
let searchField = searchBar.value(forKey: "searchField") as? UITextField
if let field = searchField {
field.backgroundColor = UIColor.defaultBackgroundColor
field.layer.cornerRadius = 15.0
field.textColor = .white
field.tintColor = .white
field.font = UIFont.systemFont(ofSize: fl(13))
field.layer.masksToBounds = true
field.returnKeyType = .search
}
But this is not working in the UISearchController.
I want to set the text color of the placeholder and the left magnifying lens icon to pure white.
(It seems there is a colored layer over them now).
In addition, the input text is black now, I want it to be white too.
In a conclusion, I want to modify the following properties.
1. textField background color
2. textFiled placeholder text color
3. textFiled text color
4. textFiled font
Anyone know how do it?
Add the following with your code in viewDidAppear:
let placeholderString = NSAttributedString(string: "Placeholder", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white])
field.attributedPlaceholder = placeholderString
let iconView = field.leftView as! UIImageView
iconView.image = iconView.image?.withRenderingMode(.alwaysTemplate)
iconView.tintColor = .white
Updata:
Put those settings in ViewDidAppear() did solve a part of my problem.
But the textfield's background color changed when I set the bar's background color.
Because searchBar.barTintColor = .red is not working in iOS11's UISearchController embedded in navigation item, I used searchBar.backgroundColor = .red
It confused me a lot.
So how to change searchBar's background and textField's background separately?
set attributedPlaceholder for textfield of search bar
#IBOutlet weak var sbSearchBar: UISearchBar!
if let textfield = sbSearchBar.value(forKey: "searchField") as? UITextField {
textfield.backgroundColor = UIColor.red
textfield.attributedPlaceholder = NSAttributedString(string: textfield.placeholder ?? "", attributes: [NSAttributedStringKey.foregroundColor : UIColor.white])
if let leftView = textfield.leftView as? UIImageView {
leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
leftView.tintColor = UIColor.white
}
}
Here is result:
Update:
I think, this may help you: how to change uitextfield color in searchcontroller?
Just apply your color combination in this code and see.
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 = // Set text color
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
}
Result:
Add the following with your code in viewDidAppear:
let placeholderString = NSAttributedString(string: "Placeholder", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white])
field.attributedPlaceholder = placeholderString
let iconView = field.leftView as! UIImageView
iconView.image = iconView.image?.withRenderingMode(.alwaysTemplate)
iconView.tintColor = .white
Update - the following is the complete code to customize UISearchController colors:
override func viewDidAppear(_ animated: Bool) {
//sets navigationbar backgroundColor
if let navigationbar = self.navigationController?.navigationBar {
navigationbar.barTintColor = UIColor.magenta
}
let searchField = searchController.searchBar.value(forKey: "searchField") as? UITextField
//sets searchBar backgroundColor
searchController.searchBar.backgroundColor = .blue
if let field = searchField {
field.layer.cornerRadius = 15.0
//sets text Color
field.textColor = .brown
//sets indicator and cancel button Color
field.tintColor = .green
field.font = UIFont.systemFont(ofSize: 13)
field.layer.masksToBounds = true
field.returnKeyType = .search
//sets placeholder text Color
let placeholderString = NSAttributedString(string: "placeholder", attributes: [NSAttributedStringKey.foregroundColor: UIColor.red])
field.attributedPlaceholder = placeholderString
//sets icon Color
let iconView = field.leftView as! UIImageView
iconView.image = iconView.image?.withRenderingMode(.alwaysTemplate)
iconView.tintColor = .cyan
//sets textField backgroundColor
if let backgroundview = field.subviews.first {
backgroundview.backgroundColor = UIColor.yellow
}
}
}
The accepted solution does not work for iOS 13, you are getting the following error (testet with Obj-C Code):
Terminating app due to uncaught exception 'NSGenericException',
reason: 'Access to UISearchBar's _searchField ivar is prohibited. This
is an application bug'
But now you have the option to access UISearchBar's TextField directly, without using a private API.
if (#available(iOS 13, *)) {
self.searchController.searchBar.searchTextField.backgroundColor = [UIColor whiteColor];
self.searchController.searchBar.searchTextField.tintColor = [UIColor darkGrayColor];
}
else {
UITextField *txfSearchField = [self.searchController.searchBar valueForKey:#"_searchField"];
UIView *background = txfSearchField.subviews.firstObject;
background.layer.cornerRadius = 10;
background.clipsToBounds = true;
background.backgroundColor=[UIColor whiteColor];
txfSearchField.tintColor=[UIColor darkGrayColor];
txfSearchField.textColor = [UIColor redColor];
}
i have embedded SearchController in navigation bar . How to Change UITextField Color The one which Holds search String To White .?
This will help you to achieve, what you want. Just apply your color combination in this code and see.
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 = // Set text color
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
}
Result:
Excellent answer, in my novice opinion we could also try using the member of the UI Search bar called searchTextField which is ultimately a subclass of UITextField but we can get away without using
if let textfield = scb.value(forKey: "searchField") as? UITextField
//we could use
let textField = scb.searchTextField
followed by the same changes made to the views layer, cornerRadius etc
I want to change the color of the text and icon in the iOS 11 searchbar when it is embedded in the navigation bar. So placeholder text, search text and search icon.
if #available(iOS 11.0, *) {
navigationController?.navigationBar.prefersLargeTitles = false
let searchController = UISearchController(searchResultsController: nil)
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
searchController.searchBar.placeholder = "Suchen"
searchController.searchBar.tintColor = .white
}
As you can see in the image, the text is grey on a deep blue background, which looks ugly. I want to text and icon to be at least white. (changing the blue background color also does not work really good, see my other question)
The only thing which works is changing the color of the blinking cursor and the "cancel" button, which is done with the .tintColor property.
Solutions which seems to work in iOS 10 and below seem not work anymore in iOS 11, so please post only solutions which you know working in iOS 11. Thanks.
Maybe I miss the point about this "automatic styling" in iOS 11. Any help is appreciated.
I just found out how to set also the rest of them: (with some help of Brandon, 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]
Thanks for the help #Brandon!
The placeholder:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).attributedPlaceholder = NSAttributedString(string: "placeholder", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white])
The white background:
let searchController = UISearchController(searchResultsController: nil)
searchController.delegate = self
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
Taken from here.
Put
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
and
UISearchBar.appearance().tintColor = UIColor.white in the AppDelegate.
Alternatively, put them both in [UIViewController viewDidLoad:]
In addition to Darko's answer.
In my case I need to get pure white search textfield color.
Also I need a custom borderLine and cornerRadius.
So if I just set background color to white, set custom corner radius and custom border line I've got something like this.
The problem is that the search bar has some subviews and I've just removed them.
Here is my code:
#interface YourViewController () <UISearchBarDelegate, UISearchControllerDelegate>
// your properties
#property (nonatomic,strong) UISearchController *searchController;
#property (nonatomic,strong) UISearchBar *searchBar;
#end
- (void)viewDidLoad {
[super viewDidLoad];
_searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
_searchController.delegate = self;
_searchController.searchBar.delegate = self;
_searchBar = self.searchController.searchBar;
if (#available(iOS 11.0, *)) {
UITextField *searchTextField = [_searchBar valueForKey:#"searchField"];
if (searchTextField != nil) {
searchTextField.layer.cornerRadius = 4.f;
searchTextField.layer.borderWidth = 1.f;
searchTextField.clipsToBounds = YES;
for (UIView *subView in searchTextField.subviews) {
[subView removeFromSuperview];
}
}
// Color for "Cancel" button
_searchBar.tintColor = [UIColor blackColor];
// Add searchController to navgationBar
_navigationItem.searchController = _searchController;
// Hide searchBar when scroll
_navigationItem.hidesSearchBarWhenScrolling = YES;
}
}
Now I've got a searchBar with pure white background, custom cornerRadius, custom border width. Also I've disabled grey highlight when tap.
Set Search Text Color
(UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]) ).defaultTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
Set Search Placeholder Color
(UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]) ).attributedPlaceholder = [NSForegroundColorAttributeName: UIColor.white]
my two cents for Swift 4.x, lightly cleaned up.
Add in controller or App Delegate:
appearance.backgroundColor = .green
let myFont = UIFont.italicSystemFont(ofSize: 12)
let attribs = [
NSAttributedString.Key(rawValue: NSAttributedString.Key.font.rawValue): myFont,
NSAttributedString.Key(rawValue: NSAttributedString.Key.foregroundColor.rawValue): UIColor.red
]
appearance.defaultTextAttributes = attribs
in controller:
self.searchBar.barTintColor = .blue
You will get Blue background, green search bar background, red italic font:
I tried Daroko solution, but i had a problem when changing the background to pure white color (it’s was grey).
My solution was to use the setSearchFieldBackgroundImage. also i don't want to rely on apple struct for getting the UITextField
if #available(iOS 11.0, *) {
let whiteImage = UIImage(color: UIColor.white, size: CGSize(width: searchController.searchBar.layer.frame.width, height: searchController.searchBar.layer.frame.height))
searchController.searchBar.setSearchFieldBackgroundImage(whiteImage, for: .normal)
self.navigationItem.searchController = searchController
self.navigationItem.hidesSearchBarWhenScrolling = true
}
public extension UIImage {
public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
let rect = CGRect(origin: .zero, size: size)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
color.setFill()
UIRectFill(rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
guard let cgImage = image?.cgImage else { return nil }
self.init(cgImage: cgImage)
} }
I used UIImage extension from :
Create UIImage with solid color in Swift
In case someone gets stuck wondering why Darkos solution doesn't work, try changing the UINavigationBar's style to default instead of black. Took me half a day to figure out ¯\_(ツ)_/¯
This code changes the background color of the text field
Swift 4
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//background color of text field
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).backgroundColor = .cyan
}
edited: sample of a UISearchBar in cyan