Cannot change search bar background color
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
.
Edited
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
.
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()
I did one UISearchBar extension & category for customize text filed within search bar.
Compatible from iOS 9 to iOS 13.
Swift 4+
import UIKitextension 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() } }}
Usage Example:
var searchController: UISearchController?searchController?.searchBar.compatibleSearchTextField.textColor = UIColor.XXXsearchController?.searchBar.compatibleSearchTextField.backgroundColor = UIColor.XXX
Objective-C
UISearchBar+SearchTextField.h
#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;@endNS_ASSUME_NONNULL_END
UISearchBar+SearchTextField.m
#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
Usage Example:
- (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}