// as UISearchBar extension
extension UISearchBar {
func changeSearchBarColor(color : UIColor) {
for subView in self.subviews {
for subSubView in subView.subviews {
if subSubView.conformsToProtocol(UITextInputTraits.self) {
let textField = subSubView as UITextField
textField.backgroundColor = color
break
}
}
}
}
}
-
-
Save wavecos/970a0e0bad82d258c22c to your computer and use it in GitHub Desktop.
let searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
//ColorImage is an image with background color
searchBar.setSearchFieldBackgroundImage(UIImage(named: "ColorImage"), for: UIControlState.normal)
this code work on iOS 10, Swift 3.0
// as UISearchBar extension
extension UISearchBar {
func changeSearchBarColor(color : UIColor) {
for subView in self.subviews {
for subSubView in subView.subviews {
if let _ = subSubView as? UITextInputTraits {
let textField = subSubView as! UITextField
textField.backgroundColor = color
break
}
}
}
}
}
Updated original code for Swift 3.0
The solution with subviews doesn't work for me. So here's my extension:
extension UISearchBar {
func changeSearchBarColor(color: UIColor) {
UIGraphicsBeginImageContext(self.frame.size)
color.setFill()
UIBezierPath(rect: self.frame).fill()
let bgImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
self.setSearchFieldBackgroundImage(bgImage, for: .normal)
}
}
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!
}
}
works perfectly
@shev-vadim-net Thanks!
extension UISearchBar {
func changeSearchBarColor(fieldColor: UIColor, backColor: UIColor, borderColor: UIColor?) {
UIGraphicsBeginImageContext(bounds.size)
backColor.setFill()
UIBezierPath(rect: bounds).fill()
setBackgroundImage(UIGraphicsGetImageFromCurrentImageContext()!, for: UIBarPosition.any, barMetrics: .default)
let newBounds = bounds.insetBy(dx: 0, dy: 8)
fieldColor.setFill()
let path = UIBezierPath(roundedRect: newBounds, cornerRadius: newBounds.height / 2)
if let borderColor = borderColor {
borderColor.setStroke()
path.lineWidth = 1 / UIScreen.main.scale
path.stroke()
}
path.fill()
setSearchFieldBackgroundImage(UIGraphicsGetImageFromCurrentImageContext()!, for: UIControlState.normal)
UIGraphicsEndImageContext()
}
}
extension UISearchBar {
var textField: UITextField? {
return subviews.map { $0.subviews.first(where: { $0 is UITextInputTraits}) as? UITextField }
.compactMap { $0 }
.first
}
}
//Usage:
let bar = UISearchBar()
bar.textField?.backgroundColor = .red
extension UISearchBar { func changeSearchBarColor(color: UIColor) { UIGraphicsBeginImageContext(self.frame.size) color.setFill() UIBezierPath(rect: self.frame).fill() let bgImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() self.setSearchFieldBackgroundImage(bgImage, for: .normal) } }
This works for me but the color goes outside the textfield bounds how can I make it stay within the textfield.
PS: I have set clipToBounds
to be true and everything I could think of and my searchbar is minimal
extension UISearchBar { func changeSearchBarColor(color: UIColor) { UIGraphicsBeginImageContext(self.frame.size) color.setFill() UIBezierPath(rect: self.frame).fill() let bgImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() self.setSearchFieldBackgroundImage(bgImage, for: .normal) } }
did you find a solution?
@hell4opt Yeah I did for the size I had to do this let size = CGSize(width: self.frame.size.width, height: 45)
you have to play with the height till you get what you want.
This is my full code for anyone having the same issue
extension UISearchBar {
func changeSearchBarColor(color: UIColor, size: CGSize) {
UIGraphicsBeginImageContext(self.frame.size)
color.setFill()
UIBezierPath(rect: self.frame).fill()
let bgImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
self.setSearchFieldBackgroundImage(bgImage, for: .normal)
}
}
Then you call it like so yourSearchBar.changeSearchBarColor(color: yellow, size: CGSize(width: yourSearchBar.frame.size.width, height: 45))
This is my full code for anyone having the same issue extension UISearchBar { func changeSearchBarColor(color: UIColor, size: CGSize) { UIGraphicsBeginImageContext(self.frame.size) color.setFill() UIBezierPath(rect: self.frame).fill() let bgImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() self.setSearchFieldBackgroundImage(bgImage, for: .normal) } }Then you call it like so
yourSearchBar.changeSearchBarColor(color: yellow, size: CGSize(width: yourSearchBar.frame.size.width, height: 45))
thanks!) but the height does not work (and the corner radius is not enough)
not working :(