Skip to content

Instantly share code, notes, and snippets.

@wavecos
Last active November 19, 2021 00:09
Show Gist options
  • Save wavecos/970a0e0bad82d258c22c to your computer and use it in GitHub Desktop.
Save wavecos/970a0e0bad82d258c22c to your computer and use it in GitHub Desktop.
Customize Color, background from UISearchBar in Swift

Customize Color, background from UISearchBar in Swift

// 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
        }
      }
    }
  }
}
@shev-vadim-net
Copy link

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)
    }
}

@astrokin
Copy link

astrokin commented Aug 7, 2017

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

@patiljignesh
Copy link

@shev-vadim-net Thanks!

@chanonly123
Copy link

chanonly123 commented Aug 20, 2018

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()
    }
}

@SeRG1k17
Copy link

SeRG1k17 commented Nov 19, 2018

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

@hechukwu
Copy link

hechukwu commented Oct 14, 2019

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

@dimabiserov
Copy link

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?

@hechukwu
Copy link

hechukwu commented Jan 7, 2020

@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.

@hechukwu
Copy link

hechukwu commented Jan 7, 2020

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))

@dimabiserov
Copy link

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment