如何更改 UISearchBar 搜索文本颜色?

如何更改 UISearchBar的文本颜色?

66030 次浏览

You have to access the UITextField inside the UISearchBar. You can do that by using valueForKey("searchField")

var textFieldInsideSearchBar = yourSearchbar.valueForKey("searchField") as? UITextField


textFieldInsideSearchBar?.textColor = yourcolor

Swift 3 update

let textFieldInsideSearchBar = yourSearchbar.value(forKey: "searchField") as? UITextField


textFieldInsideSearchBar?.textColor = yourcolor

If you want to set text color for UISearchBar in storyboard (without code), it is easy to do as well (in identity inspector). Here is a red text for search bar.

enter image description here

public extension UISearchBar {


public func setTextColor(color: UIColor) {
let svs = subviews.flatMap { $0.subviews }
guard let tf = (svs.filter { $0 is UITextField }).first as? UITextField else { return }
tf.textColor = color
}
}

You can do this by accessing the UITextField inside the searchBar, then you can change its background color, text color, and all other UITextField properties

add the following extension to access the textField

extension UISearchBar {
/// Return text field inside a search bar
var textField: UITextField? {
let subViews = subviews.flatMap { $0.subviews }
guard let textField = (subViews.filter { $0 is UITextField }).first as? UITextField else { return nil
}
return textField
}
}

The most convenient way I think is to set a textColor property in UISearchBar.

Swift 3.0

    extension UISearchBar {


var textColor:UIColor? {
get {
if let textField = self.value(forKey: "searchField") as?
UITextField  {
return textField.textColor
} else {
return nil
}
}


set (newValue) {
if let textField = self.value(forKey: "searchField") as?
UITextField  {
textField.textColor = newValue
}
}
}
}

Usage

searchBar.textColor = UIColor.blue // Your color

Swift 2.3

extension UISearchBar {


var textColor:UIColor? {
get {
if let textField = self.valueForKey("searchField") as? UITextField  {
return textField.textColor
} else {
return nil
}
}


set (newValue) {
if let textField = self.valueForKey("searchField") as? UITextField  {
textField.textColor = newValue
}
}
}
}

You would use it as:

searchBar.textColor = UIColor.blueColor() // Your color

This works for me on iOS 11, Xcode 9:

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).textColor = UIColor.blue

I write it in the AppDelegate but I guess it works if you put it somewhere else too.

If you only need to make it readable on a dark background you can change the barStyle. The following makes text and buttons in the searchbar white:

searchController.searchBar.barStyle = .black

In my situation solution is

id appearance = [UITextField appearanceWhenContainedInInstancesOfClasses:@[UISearchBar.class, BCRSidebarController.class]];
[appearance setTextColor:[UIColor.whiteColor colorWithAlphaComponent:0.56]];

Working in Swift 4 for me:

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedStringKey.foregroundColor.rawValue: UIColor.white]

Swift 4.2, IOS 12:

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]

(This solution only tested for Xcode 10 & iOS 12.) Add an extension to access the search bar's text field:

extension UISearchBar {
var textField: UITextField? {
return subviews.first?.subviews.compactMap { $0 as? UITextField }.first
}
}

Then use that property to set the text color of the text field in your search bar:

let searchBar = UISearchBar()
searchBar.textField?.textColor = UIColor.white // or whichever color you want

// EDIT

The code above does not work for iOS 13. A better way to handle this is to use:

extension UISearchBar {
var textField: UITextField? {
return self.subviews(ofType: UITextField.self).first
}
}


extension UIView {
var recursiveSubviews: [UIView] {
return self.subviews + self.subviews.flatMap { $0.recursiveSubviews }
}


func subviews<T: UIView>(ofType: T.Type) -> [T] {
return self.recursiveSubviews.compactMap { $0 as? T }
}
}

Here is a Xamarin.iOS C# version of the "find the UITextField" approach. It will not crash if the UITextField disappears in future iOS view hierarchy.

var tf = searchBar.AllSubViews().FirstOrDefault(v => v is UITextField);
if (tf != null)
(tf as UITextField).TextColor = UIColor.White;


public static IEnumerable<UIView> AllSubViews(this UIView view)
{
foreach (var v in view.Subviews)
{
yield return v;
foreach (var sv in v.AllSubViews())
{
yield return sv;
}
}
}

Since Xcode 11 and iOS 13 it has become possible to access the text field directly:

searchBar.searchTextField

You could write some code to always make it accessible like this.

extension UISearchBar {
public var textField: UITextField? {
if #available(iOS 13.0, *) {
return searchTextField
}


guard let firstSubview = subviews.first else {
assertionFailure("Could not find text field")
return nil
}


for view in firstSubview.subviews {
if let textView = view as? UITextField {
return textView
}
}


assertionFailure("Could not find text field")


return nil
}
}

You could also make it not optional with fatal errors, this code is tested since iOS 7 up to iOS 13GM. But i would just go for the optional version.

extension UISearchBar {
public var textField: UITextField {
if #available(iOS 13.0, *) {
return searchTextField
}


guard let firstSubview = subviews.first else {
fatalError("Could not find text field")
}


for view in firstSubview.subviews {
if let textView = view as? UITextField {
return textView
}
}


fatalError("Could not find text field")
}
}

Obj-C

UITextField *textField = [self.yourSearchbar valueForKey:@"_searchField"];
textField.textColor = [UIColor redColor];

Swift 4.x

let textField = yourSearchbar.value(forKey: "searchField") as? UITextField
textField?.textColor = UIColor.red

I tried a few of the solutions written above but they didn't work (anymore, I guess).

If you only want to handle iOS 13:

mySearchBar.searchTextField.textColor = .red

But if you want to handle older iOS too, Here is the way I did :

Create a custom UISearchBar class, called SearchBar : UISearchBar, UISearchBarDelegate This SearchBar will have the UISearchBarDelegate methods I wanna handle and its delegate set.

And I add to the class:

    var textField: UITextField? {
if #available(iOS 13.0, *) {
return self.searchTextField
}
return subviews.first?.subviews.first(where: { $0 as? UITextField != nil }) as? UITextField
}

Short explanation:

With iOS13 now, you can access the UITextField thanks to UISearchBar.searchTextField, which is of type UISearchTextField, which inherits from UITextField.

Since I know my hierarchy, I know my textField won't be nill for older versions so in both case, I get a textfield I can easily customize, working on every version, from 9 to 13 today.

Here is the full code needed to make it work:


class SearchBar: UISearchBar, UISearchBarDelegate {


var textField: UITextField? {
if #available(iOS 13.0, *) {
return self.searchTextField
}
return subviews.first?.subviews.first(where: { $0 as? UITextField != nil }) as? UITextField
}




override func awakeFromNib() {
super.awakeFromNib()


delegate = self


if let textField = textField {
textField.textColor = .red
textField.clearButtonMode = .whileEditing
textField.returnKeyType = .search
}
}


}

You can also set some customization on SearchBar by adding this on the :

        let searchBar = UISearchBar.appearance(whenContainedInInstancesOf: [SearchBar.self])
searchBar.backgroundImage = UIImage()
searchBar.isTranslucent = false
searchBar.returnKeyType = .search

Then you set it to the XIB / Storyboard and you handle it like if it were a simple UISearchBar (if you did not forget the delegates !).

//Try this guy

yourSearchbar.searchTextField.textColor = .white

Try this,

searchBar.searchTextField.textColor = .white

I am using this with app targeted iOS 11 onwards.

[Update] I observed, the app crashes on older versions (< iOS 13), But compiler never complained about the version check, someone please explain why this happened.

Swift 5.2 & iOS 13.3.1:-

It works fine.

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]


Swift 5:

searchBar[keyPath: \.searchTextField].textColor = UIColor(...)

Swift 5 Xcode 11.4 iOS 13.4

    UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).textColor = .white
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).font = .systemFont(ofSize: 13)

In Swift 5 you can do something like below:

yourSearchBar.searchTextField.textColor = .yourColor

This worked for me.

    if #available(iOS 13.0, *) {
searchBar.searchTextField.textColor = .white
}

you can set the color for self.searchBar.searchTextField.textColor below code in viewDidLoad works.

- (void)viewDidLoad {
[super viewDidLoad];
self.searchBar.searchTextField.textColor = [UIColor whiteColor];
}

SwiftUI, Swift 5

In SwiftUI, the

init(){


UITextfiled.appearance().textColor = .white
}

doesn't work. But you can just use the

.foregroundColor(.white)

modifier to change the searchable()'s text color.

If you also want to change the tintColor of the searchbar inside a NavigationView{}. You could init the inti() function of the view.

init(){


UINavigationBar.appearance().tintColor = .white


}
var body:some View{
   

NavigationView{
   

}
}