Changing cursor color on UISearchBar without changing tintColor
-
20-12-2019 - |
Question
I want my searchBar's tint color to be white (meaning the cancel button be white). The cursor is not visible when the tint color is white. Is there a way to set cursor color separately?
Solution
Set your tint color to the color you want the cancel button to be and then use the UIAppearance Protocol to change the tint color on the text field to be the color you wish the cursor to be. Ex:
[self.searchBar setTintColor:[UIColor whiteColor]];
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:[UIColor darkGrayColor]];
OTHER TIPS
If you're fond of functional, yet annoying one-liners in Swift, I got Benjamin's for loop down to this:
searchController.searchBar.tintColor = UIColor.whiteColor()
searchController.searchBar.subviews[0].subviews.flatMap(){ $0 as? UITextField }.first?.tintColor = UIColor.blueColor()
Swift 3.0 and 4 version
searchController.searchBar.tintColor = .white
UITextField.appearance(whenContainedInInstancesOf: [type(of: searchController.searchBar)]).tintColor = .black
Note that searchBar can't be optional.
Compact Swift 2.0 solution using for-where syntax (no need to break loop):
// Make SearchBar's tint color white to get white cancel button.
searchBar.tintColor = UIColor.white()
// Loop into it's subviews and find TextField, change tint color to something else.
for subView in searchBar.subviews[0].subviews where subView.isKindOfClass(UITextField) {
subView.tintColor = UIColor.darkTextColor()
}
This seemed to work for me in swift as well.
searchController.searchBar.tintColor = UIColor.whiteColor()
UITextField.appearanceWhenContainedInInstancesOfClasses([searchController.searchBar.dynamicType]).tintColor = UIColor.blackColor()
For those looking to do the same in Swift, here is a solution I came accros after quite a lot of trouble :
override func viewWillAppear(animated: Bool) {
self.searchBar.tintColor = UIColor.whiteColor()
let view: UIView = self.searchBar.subviews[0] as! UIView
let subViewsArray = view.subviews
for (subView: UIView) in subViewsArray as! [UIView] {
println(subView)
if subView.isKindOfClass(UITextField){
subView.tintColor = UIColor.blueColor()
}
}
}
I would just add an extension to UISearchBar with the following code.
extension UISearchBar {
var cursorColor: UIColor! {
set {
for subView in self.subviews[0].subviews where ((subView as? UITextField) != nil) {
subView.tintColor = newValue
}
}
get {
for subView in self.subviews[0].subviews where ((subView as? UITextField) != nil) {
return subView.tintColor
}
// Return default tintColor
return UIColor.eightBit(red: 1, green: 122, blue: 255, alpha: 100)
}
}
}
iOS 9 and above
The easiest way to set a tintColor different for cancel button and textField, use this:
[self.searchBar setTintColor:[UIColor whiteColor]];
[[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTintColor:UIColor.blueColor];
This is the easiest solution.
let textField = self.searchBar.value(forKey: "searchField") as! UITextField
textField.tintColor = UIColor.white
Easiest in Swift 5:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = .black
Here is a "functional" version of Felipe's answer (Swift 4.2)
// Make SearchBar's tint color white to get white cancel button.
searchBar.tintColor = .white
// Get the TextField subviews, change tint color to something else.
if let textFields = searchBar.subviews.first?.subviews.compactMap({ $0 as? UITextField }) {
textFields.forEach { $0.tintColor = UIColor.darkGray }
}