How to change UISearchBar Placeholder and image tint color?
Solution 1
If you have a custom image you could use, you can set the image and change the placeholder text color using something similar to the following:
[searchBar setImage:[UIImage imageNamed:@"SearchWhite"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
UITextField *searchTextField = [searchBar valueForKey:@"_searchField"];
if ([searchTextField respondsToSelector:@selector(setAttributedPlaceholder:)]) {
UIColor *color = [UIColor purpleColor];
[searchTextField setAttributedPlaceholder:[[NSAttributedString alloc] initWithString:@"Search" attributes:@{NSForegroundColorAttributeName: color}]];
}
In that example I used purpleColor, instead you can use the + (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha
method to create your custom dark green color.
EDIT: I just realized you were writing it in swift... duh. Quickly typed this out so I didn't leave the answer in just Obj-C.
searchBar.setImage(UIImage(named: "SearchWhite"), forSearchBarIcon: UISearchBarIcon.Search, state: UIControlState.Normal);
var searchTextField: UITextField? = searchBar.valueForKey("searchField") as? UITextField
if searchTextField!.respondsToSelector(Selector("attributedPlaceholder")) {
var color = UIColor.purpleColor()
let attributeDict = [NSForegroundColorAttributeName: UIColor.purpleColor()]
searchTextField!.attributedPlaceholder = NSAttributedString(string: "search", attributes: attributeDict)
}
Swift 3.0
var searchTextField: UITextField? = searchBar.value(forKey: "searchField") as? UITextField
if searchTextField!.responds(to: #selector(getter: UITextField.attributedPlaceholder)) {
let attributeDict = [NSForegroundColorAttributeName: UIColor.white]
searchTextField!.attributedPlaceholder = NSAttributedString(string: "Search", attributes: attributeDict)
}
Solution 2
Details
- Xcode Version 11.0 (11A420a), iOS 13, swift 5
Solution
import UIKit
extension UISearchBar {
func getTextField() -> UITextField? { return value(forKey: "searchField") as? UITextField }
func set(textColor: UIColor) { if let textField = getTextField() { textField.textColor = textColor } }
func setPlaceholder(textColor: UIColor) { getTextField()?.setPlaceholder(textColor: textColor) }
func setClearButton(color: UIColor) { getTextField()?.setClearButton(color: color) }
func setTextField(color: UIColor) {
guard let textField = getTextField() else { return }
switch searchBarStyle {
case .minimal:
textField.layer.backgroundColor = color.cgColor
textField.layer.cornerRadius = 6
case .prominent, .default: textField.backgroundColor = color
@unknown default: break
}
}
func setSearchImage(color: UIColor) {
guard let imageView = getTextField()?.leftView as? UIImageView else { return }
imageView.tintColor = color
imageView.image = imageView.image?.withRenderingMode(.alwaysTemplate)
}
}
private extension UITextField {
private class Label: UILabel {
private var _textColor = UIColor.lightGray
override var textColor: UIColor! {
set { super.textColor = _textColor }
get { return _textColor }
}
init(label: UILabel, textColor: UIColor = .lightGray) {
_textColor = textColor
super.init(frame: label.frame)
self.text = label.text
self.font = label.font
}
required init?(coder: NSCoder) { super.init(coder: coder) }
}
private class ClearButtonImage {
static private var _image: UIImage?
static private var semaphore = DispatchSemaphore(value: 1)
static func getImage(closure: @escaping (UIImage?)->()) {
DispatchQueue.global(qos: .userInteractive).async {
semaphore.wait()
DispatchQueue.main.async {
if let image = _image { closure(image); semaphore.signal(); return }
guard let window = UIApplication.shared.windows.first else { semaphore.signal(); return }
let searchBar = UISearchBar(frame: CGRect(x: 0, y: -200, width: UIScreen.main.bounds.width, height: 44))
window.rootViewController?.view.addSubview(searchBar)
searchBar.text = "txt"
searchBar.layoutIfNeeded()
_image = searchBar.getTextField()?.getClearButton()?.image(for: .normal)
closure(_image)
searchBar.removeFromSuperview()
semaphore.signal()
}
}
}
}
func setClearButton(color: UIColor) {
ClearButtonImage.getImage { [weak self] image in
guard let image = image,
let button = self?.getClearButton() else { return }
button.imageView?.tintColor = color
button.setImage(image.withRenderingMode(.alwaysTemplate), for: .normal)
}
}
var placeholderLabel: UILabel? { return value(forKey: "placeholderLabel") as? UILabel }
func setPlaceholder(textColor: UIColor) {
guard let placeholderLabel = placeholderLabel else { return }
let label = Label(label: placeholderLabel, textColor: textColor)
setValue(label, forKey: "placeholderLabel")
}
func getClearButton() -> UIButton? { return value(forKey: "clearButton") as? UIButton }
}
Full Sample
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let searchBar = UISearchBar(frame: CGRect(x: 0, y: 20, width: UIScreen.main.bounds.width, height: 44))
searchBar.searchBarStyle = .default
view.addSubview(searchBar)
searchBar.placeholder = "placeholder"
searchBar.set(textColor: .brown)
searchBar.setTextField(color: UIColor.green.withAlphaComponent(0.3))
searchBar.setPlaceholder(textColor: .white)
searchBar.setSearchImage(color: .white)
searchBar.setClearButton(color: .red)
}
}
Result
Solution 3
Swift 3: If you want to change the placeholder, clearbutton and magnifier glass
let textFieldInsideSearchBar = searchBar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.textColor = UIColor.white
let textFieldInsideSearchBarLabel = textFieldInsideSearchBar!.value(forKey: "placeholderLabel") as? UILabel
textFieldInsideSearchBarLabel?.textColor = UIColor.white
let clearButton = textFieldInsideSearchBar?.value(forKey: "clearButton") as! UIButton
clearButton.setImage(clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate), for: .normal)
clearButton.tintColor = UIColor.white
let glassIconView = textFieldInsideSearchBar?.leftView as? UIImageView
glassIconView?.image = glassIconView?.image?.withRenderingMode(.alwaysTemplate)
glassIconView?.tintColor = UIColor.white
Solution 4
You can change the color of the text without violating the private api rule:
UILabel.appearanceWhenContainedInInstancesOfClasses([UITextField.self]).textColor = UIColor.whiteColor()
Solution 5
I made a Swift 4.1 search bar extension:
import Foundation
import UIKit
extension UISearchBar{
func setTextField(placeHolderColor:UIColor = .gray,placeHolder:String = "Search Something",textColor:UIColor = .white,backgroundColor:UIColor = .black,
placeHolderFont:UIFont = UIFont.systemFont(ofSize: 12.0),
textFont:UIFont = UIFont.systemFont(ofSize: 12.0) ){
for item in self.subviews{
for mainView in (item as UIView).subviews{
mainView.backgroundColor = backgroundColor
if mainView is UITextField{
let textField = mainView as? UITextField
if let _textF = textField{
_textF.text = "success"
_textF.textColor = textColor
_textF.font = textFont
_textF.attributedPlaceholder = NSMutableAttributedString.init(string: placeHolder, attributes: [NSAttributedStringKey.foregroundColor : placeHolderColor,
NSAttributedStringKey.font : placeHolderFont])
}
}
}
}
}
}
You can use this for your searchBar
like this :
controller.searchBar.setTextField(placeHolderColor: .white,
placeHolder: "Search A Pet",
textColor: .white,
backgroundColor: .green,
placeHolderFont: UIFont.systemFont(ofSize: 14.0),
textFont: UIFont.systemFont(ofSize: 14.0))
Kyle Bashour
Updated on May 13, 2020Comments
-
Kyle Bashour almost 4 years
I've been trying search results for hours, but I can't get this figured out. Perhaps it isn't possible. I'm trying to change the tint color of the placeholder text and magnifying glass of a UISearchBar. I'm only targeting iOS 8.0+ if that matters. Here's my code and what it looks like now:
let searchBar = UISearchBar() searchBar.placeholder = "Search" searchBar.searchBarStyle = UISearchBarStyle.Minimal searchBar.tintColor = UIColor.whiteColor()
I'd like for the search and magnifying glass to be white, or perhaps a dark green.
-
Kyle Bashour about 9 yearsThis is perfect, thank you so much. I hadn't seen
searchBar.valueForKey("searchField") as? UITextField
before, which is brilliant. Any chance you know how to change the clear button (the little round x) as well? -
c_rath about 9 yearsI would imagine it would be the same way as the setImage but instead of using the UISearchBarIcon.Search, you would instead use .Clear??? I haven't actually tried that though. Outside of that I know the actual word "Cancel" is affected by the searchBar.tintColor...
-
Iulian Onofrei over 8 yearsAccessing private properties or APIs is a sure way to get your app rejected.
-
netshark1000 about 8 yearsdon't use private APIs
-
Elijah about 8 yearsappearanceWhenContainedInInstancesOfClasses is only available in ios9+
-
ethanfox27 about 7 yearsDo you have the source code for this? I am having trouble understanding this.
-
Jerome about 7 yearsHi @ethanfox27, here is the source code, hope for help. github.com/JeromeTW/XZY-s-Blog/blob/master/ReadMe.txt github.com/JeromeTW/XZY-s-Blog/blob/master/…
-
Ansal Antony almost 7 yearsself.searcBar.setTextFieldColor(color: .white) not working why ? still showing light lightGray color, but other colors are working but white not working any idea ? ....
-
Renato over 6 yearsI've been trying to get this to work on iOS 11 when SearchBar is within the NavigationBar without success. Any ideas?
-
Vasily Bodnarchuk over 6 yearsHello Renato. I can't understand your problem. You can't add SearchBar to NavigationBar?
-
Mikhail Sein about 6 yearsThank you so much!
-
John Stephen about 6 yearsThe question is how to change the colors, not how to set the text
-
Gautam Sareriya about 6 yearsMagnifying glass and search placeholder not in centre as per your output.
-
Kevin_TA almost 6 yearsThis solution looks great, but for
UISearchController
you need to subclass bothUISearchController
and it'sUISearchBar
. Even then, the clear button coloring still doesn't work. Any ideas why? -
feb almost 6 yearsThis is a good solution but it can easily be broken if Apple decides to change the internal subview structure of UISearchBar in a future iOS release. I'm amazed they don't expose simple appearance customisations like this as a public API.
-
Vineeth Joseph almost 6 years@VasilyBodnarchuk Great answer. In swift 4 I think NSForegroundColorAttributeName has been changed to NSAttributedStringKey.foregroundColor.
-
Chintan Shah over 5 yearsGreat Solution! One issue is
ClearButtonColor
is not working in iOS 12.0. -
Isuru almost 5 years@VasilyBodnarchuk I think what @Renato meant was if you add the searchController straight to the navigationItem like this
navigationItem.searchController = searchController
, these methods don't work. I noticed however if you add the searchBar of the searchController to the titleView of the navigationItem like this,navigationItem.titleView = searchController.searchBar
, it works. -
Vasily Bodnarchuk almost 5 years@Isuru It can be true. Because
searchController
has ownsearchBar
. In this case I suggest to inheritsearchController
and updated itssearchBar
. -
Soumen over 4 yearsSearchbar's placeholder color is not changing on iOS 13.
-
Tum about 4 yearsNice solution! Icon works fine, placeholder text doesn't change for me though.