Reputation: 7569
I have a search bar:
let searchBar:UISearchBar = UISearchBar(frame: CGRectMake((searchView.frame.width - UIScreen.mainScreen().bounds.width / 1.6) / 2, 0, UIScreen.mainScreen().bounds.width / 1.6, 24))
and I want to change text input part background color. For this I've tried:
searchBar.barTintColor = UIColor(red: 0/255, green: 74/255, blue: 103/255, alpha: 1)
searchBar.backgroundColor = UIColor.redColor()
but these both variants do not work. How can I change background color of my UISearchBar textInput part and what I did wrong?
Upvotes: 32
Views: 61250
Reputation: 12292
class UsableUISearchBar: UISearchBar {
override init(frame: CGRect) {
super.init(frame: frame)
common()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
common()
}
func common() {
barTintColor = .clear
searchTextField.backgroundColor = .darkGray
searchTextField.leftView?.tintColor = .white
}
}
Upvotes: 0
Reputation: 21
For Swift 5 iOS 13+
The first line is to change the colour of the outside box colour and the second one is to change the colour of inside the search text box.
searchBar.barTintColor = .red
searchBar.searchTextField.backgroundColor = .white
Upvotes: 2
Reputation: 1188
Search Bar Color Change
Simply change the searchbar style to minimal and it will show the search bar's background color. To change the oval inside the box aka the textfield. Just change the searchbar.textfield.backgroundcolor attribute.
searchbar.searchBarStyle = .minimal
searchbar.backgroundColor = //color here
searchbar.searchTextField.backgroundColor = //color here
Upvotes: 6
Reputation: 529
Swift 5 extension:
Works perfect on all iOS versions
import UIKit
extension UISearchBar {
func setupSearchBar(background: UIColor = .white, inputText: UIColor = .black, placeholderText: UIColor = .gray, image: UIColor = .black) {
self.searchBarStyle = .minimal
self.barStyle = .default
// IOS 12 and lower:
for view in self.subviews {
for subview in view.subviews {
if subview is UITextField {
if let textField: UITextField = subview as? UITextField {
// Background Color
textField.backgroundColor = background
// Text Color
textField.textColor = inputText
// Placeholder Color
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : placeholderText])
// Default Image Color
if let leftView = textField.leftView as? UIImageView {
leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
leftView.tintColor = image
}
let backgroundView = textField.subviews.first
backgroundView?.backgroundColor = background
backgroundView?.layer.cornerRadius = 10.5
backgroundView?.layer.masksToBounds = true
}
}
}
}
// IOS 13 only:
if let textField = self.value(forKey: "searchField") as? UITextField {
// Background Color
textField.backgroundColor = background
// Text Color
textField.textColor = inputText
// Placeholder Color
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : placeholderText])
// Default Image Color
if let leftView = textField.leftView as? UIImageView {
leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
leftView.tintColor = image
}
}
}
}
Upvotes: 9
Reputation: 600
I did one UISearchBar extension & category for customize text filed within search bar.
import UIKit
extension UISearchBar {
// Due to searchTextField property who available iOS 13 only, extend this property for iOS 13 previous version compatibility
var compatibleSearchTextField: UITextField {
guard #available(iOS 13.0, *) else { return legacySearchField }
return self.searchTextField
}
private var legacySearchField: UITextField {
if let textField = self.subviews.first?.subviews.last as? UITextField {
// Xcode 11 previous environment
return textField
} else if let textField = self.value(forKey: "searchField") as? UITextField {
// Xcode 11 run in iOS 13 previous devices
return textField
} else {
// exception condition or error handler in here
return UITextField()
}
}
}
var searchController: UISearchController?
searchController?.searchBar.compatibleSearchTextField.textColor = UIColor.XXX
searchController?.searchBar.compatibleSearchTextField.backgroundColor = UIColor.XXX
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UISearchBar (SearchTextField)
// Due to searchTextField property who available iOS 13 only, extend this property for iOS 13 previous version compatibility
@property (nonatomic, readonly) UITextField *compatibleSearchTextField;
@end
NS_ASSUME_NONNULL_END
#import "UISearchBar+SearchTextField.h"
@implementation UISearchBar (SearchTextField)
- (UITextField *)compatibleSearchTextField {
if (@available(iOS 13.0, *)) {
#ifdef __IPHONE_13_0
return self.searchTextField;
#else
// Xcode 11 run in iOS 13 previous devices
return (UITextField *)[self valueForKey:@"searchField"];
#endif
} else {
// Xcode 11 previous environment
return [[[self.subviews firstObject] subviews] lastObject];
}
}
@end
- (UISearchBar *)searchBar {
if (!_searchBar) {
_searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(X, X, X, X)];
_searchBar.compatibleSearchTextField.textColor = [UIColor XXX];
_searchBar.compatibleSearchTextField.backgroundColor = [UIColor XXX];
}
return _searchBar
}
Upvotes: 16
Reputation: 850
Swift 5:
searchController.searchBar.searchTextField.backgroundColor = .white
Upvotes: 13
Reputation: 87
Faced the same issue , for iOS 13+ , textFiled can be get by as follow
var searchText : UITextField?
if #available(iOS 13.0, *) {
searchText = searchBar.searchTextField
}
else {
searchText = searchBar.value(forKey: "_searchField") as? UITextField
}
searchText?.backgroundColor = .red
Upvotes: 9
Reputation: 61
I was experimenting with the properties of searchBar and searchTextField when I found a solution to the above.
Below, I have listed the steps in order to achieve the desired result:
Further, I have provided the code below for your reference:
let searchController = UISearchController(searchResultsController: nil)
navigationItem.searchController = searchController
searchController.searchBar.barTintColor = viewBackgroundColor
searchController.searchBar.backgroundColor = viewBackgroundColor
searchController.searchBar.searchTextField.borderStyle = .none
searchController.searchBar.searchTextField.backgroundColor = .white
searchController.searchBar.searchTextField.layer.cornerRadius = 10
searchController.searchBar.searchTextField.clipsToBounds = true
Note: searchTextField is in Beta and available on iOS 13
Upvotes: 6
Reputation: 4066
A UISearchBar extension using Swift 4 based on the most voted answer
extension UISearchBar {
func tfBackgroundColor(color: UIColor){
for view in self.subviews {
for subview in view.subviews {
if subview is UITextField {
let textField: UITextField = subview as! UITextField
textField.backgroundColor = color
}
}
}
}
}
Upvotes: 1
Reputation: 89
Here's the solution
func configureSearchBar() {
for textField in searchBar.subviews.first!.subviews where textField is UITextField {
textField.backgroundColor = .cyan
}
}
Upvotes: 0
Reputation: 1016
Like @aliamcami, all the answers before did not work as I would expect, either the answer did not work for me or it works but it needs too much "dummy" code. So I share another answer wrote in Swift 4 with simplified logic:
for textField in searchController.searchBar.subviews.first!.subviews where textField is UITextField {
textField.subviews.first?.backgroundColor = .white
textField.subviews.first?.layer.cornerRadius = 10.5 //I set 10.5 because is approximately the system value
textField.subviews.first?.layer.masksToBounds = true
//Continue changing more properties...
}
textField.subviews.first
is the "_UISearchBarSearchFieldBackgroundView" subview which add visual effects behind the UIFieldEditor
.
After some development and many bugs, I finished with this elegant solution (that I am sure Apple would not be happy to approve, but I do not know) that works from iOS 10 to iOS 12:
if let textField = searchBar.value(forKey: "searchField") as? UITextField {
textField.backgroundColor = myColor
//textField.font = myFont
//textField.textColor = myTextColor
//textField.tintColor = myTintColor
// And so on...
let backgroundView = textField.subviews.first
if #available(iOS 11.0, *) { // If `searchController` is in `navigationItem`
backgroundView?.backgroundColor = UIColor.white.withAlphaComponent(0.3) //Or any transparent color that matches with the `navigationBar color`
backgroundView?.subviews.forEach({ $0.removeFromSuperview() }) // Fixes an UI bug when searchBar appears or hides when scrolling
}
backgroundView?.layer.cornerRadius = 10.5
backgroundView?.layer.masksToBounds = true
//Continue changing more properties...
}
When the searchBar
is in the tableHeaderView
the above code can be called in viewWillAppear
, but if it is in the navigationItem
on iOS 11 and above it should be called in viewDidAppear
.
Upvotes: 22
Reputation: 91
Here's the solution:
func customizeSearchBar(){
if let textfield = searchController.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;
}
}
}
But Please note that this works only in iOS 11.0 and later. So don't forget to add before that
if #available(iOS 11.0, *) {}
Upvotes: 2
Reputation: 23407
You are adding the below code in ViewDidLoad and Change the textfield background color RED,
for subView in searchBar.subviews
{
for subView1 in subView.subviews
{
if subView1.isKindOfClass(UITextField)
{
subView1.backgroundColor = UIColor.redColor()
}
}
}
Red Color of TextField in SearchBar.
Upvotes: 11
Reputation: 1
I just came to share the ONLY way I could change the background color for the searchbar textField because I havent seen it on any answer yet, and none of the other suggestions, here or the in other sites, have worked for me.
Get the textField from the search bar, like the answer from @Steve ... anything works here as long as you get the textField. This was not my problem, the thing is, it did not metter the colors I setted here, it was not working
extension UISearchBar {
var textField: UITextField? {
return subviews.first?.subviews.first(where: { $0.isKind(of: UITextField.self) }) as? UITextField
}
}
Make a new layer with the size of the navigationBar
let layer = CALayer()
layer.backgroundColor = UIColor.white.withAlphaComponent(0.5).cgColor //Set your color here
layer.frame = navigationBar.frame
navigationBar.textField?.layer.masksToBounds = true //to make sure you get the rounded corners
navigationBar.textField?.layer.cornerRadius = 14 //Round it as you wish
navigationBar.textField?.layer.addSublayer(layer)
Upvotes: 0
Reputation: 951
FWIW I'm solving this problem by creating a computed variable named textField.
extension UISearchBar {
var textField: UITextField? {
return subviews.first?.subviews.first(where: { $0.isKind(of: UITextField.self) }) as? UITextField
}
}
Upvotes: 4
Reputation: 816
Set any color you want. SWIFT 3
public extension UISearchBar {
public func setStyleColor(_ color: UIColor) {
tintColor = color
guard let tf = (value(forKey: "searchField") as? UITextField) else { return }
tf.textColor = color
if let glassIconView = tf.leftView as? UIImageView, let img = glassIconView.image {
let newImg = img.blendedByColor(color)
glassIconView.image = newImg
}
if let clearButton = tf.value(forKey: "clearButton") as? UIButton {
clearButton.setImage(clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate), for: .normal)
clearButton.tintColor = color
}
}
}
extension UIImage {
public func blendedByColor(_ color: UIColor) -> UIImage {
let scale = UIScreen.main.scale
if scale > 1 {
UIGraphicsBeginImageContextWithOptions(size, false, scale)
} else {
UIGraphicsBeginImageContext(size)
}
color.setFill()
let bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height)
UIRectFill(bounds)
draw(in: bounds, blendMode: .destinationIn, alpha: 1)
let blendedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return blendedImage!
}
}
Upvotes: 1
Reputation: 1571
I do it with this way(Swift 3+ solution):
let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.backgroundColor = UIColor.red
Upvotes: 9
Reputation: 576
For Swift 3+, use this:
for subView in searchController.searchBar.subviews {
for subViewOne in subView.subviews {
if let textField = subViewOne as? UITextField {
subViewOne.backgroundColor = UIColor.red
//use the code below if you want to change the color of placeholder
let textFieldInsideUISearchBarLabel = textField.value(forKey: "placeholderLabel") as? UILabel
textFieldInsideUISearchBarLabel?.textColor = UIColor.blue
}
}
}
Upvotes: 10
Reputation: 1408
The way to do this only using Apple APIs is to create an image and use setSearchFieldBackgroundImage
:
self.searchBar.setSearchFieldBackgroundImage(UIImage(named: "SearchFieldBackground"), for: UIControlState.normal)
It will even animate the corners properly if you create a rounded rect and dynamically show and hide buttons.
Upvotes: 12
Reputation: 31
A very common answer to this question on the web is this solution described above:
for subView in searchBar.subviews {
for subViewInSubView in subView.subviews {
if subViewInSubView.isKindOfClass(UITextField) {
subViewInSubView.backgroundColor = UIColor.purpleColor()
}
}
}
But it didn't work for me using XCode 7 and iOS 9, and I noticed that around the web many others reported that it didn't work for them, either. I discovered that the UITextField subview isn't created (or at least it isn't added as a subview) until it is referenced, and one way it can be referenced is by the placeholder field, e.g., one could add this line before searching the subviews for the UITextField class:
searchBar.placeholder = searchBar.placeholder
Upvotes: 3
Reputation: 1155
Just like this
let searchBar:UISearchBar = UISearchBar(frame: CGRectMake((searchView.frame.width - UIScreen.mainScreen().bounds.width / 1.6) / 2, 0, UIScreen.mainScreen().bounds.width / 1.6, 24))
let searchTextField = searchBar.valueForKey("_searchField") as? UITextField
searchTextField?.backgroundColor = UIColor.redColor()
Upvotes: 6
Reputation: 2026
Just try your code as below in playground. If still that won't work, add more code to your question...
let searchView = UIView(frame: CGRect(x: 0.0,y: 0.0, width: 100, height: 50))
let searchBar:UISearchBar = UISearchBar(frame: CGRectMake((searchView.frame.width - UIScreen.mainScreen().bounds.width / 1.6) / 2, 0, UIScreen.mainScreen().bounds.width / 1.6, 24))
for subView in searchBar.subviews {
for subViewInSubView in subView.subviews {
if subViewInSubView.isKindOfClass(UITextField) {
subViewInSubView.backgroundColor = UIColor.purpleColor()
}
}
}
Upvotes: 0
Reputation: 2941
If you only want to change it in your ViewController and don't want anywhere else to effect then use
for view in searchBar.subviews {
for subview in view.subviews {
if subview .isKindOfClass(UITextField) {
let textField: UITextField = subview as! UITextField
textField.backgroundColor = UIColor.redColor()
}
}
}
But if you want it to be change in whole app and targeting the iOS 9.0 or later then should be using appearanceWhenContainedInInstancesOfClasses like
UITextField.appearanceWhenContainedInInstancesOfClasses([UISearchBar.self]).backgroundColor = UIColor.redColor()
Upvotes: 16